Coverage Report

Created: 2026-02-22 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/init.c
Line
Count
Source
1
/*
2
 * Copyright 2016-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include "internal/e_os.h"
11
#include "crypto/cryptlib.h"
12
#include <openssl/err.h>
13
#include "crypto/rand.h"
14
#include "internal/bio.h"
15
#include <openssl/evp.h>
16
#include "crypto/evp.h"
17
#include "internal/conf.h"
18
#include "crypto/async.h"
19
#include "internal/comp.h"
20
#include "internal/err.h"
21
#include "crypto/err.h"
22
#include "crypto/objects.h"
23
#include <stdlib.h>
24
#include <assert.h>
25
#include "internal/thread_once.h"
26
#include "crypto/dso_conf.h"
27
#include "internal/dso.h"
28
#include "crypto/store.h"
29
#include <openssl/cmp_util.h> /* for OSSL_CMP_log_close() */
30
#include <openssl/trace.h>
31
#include <openssl/ssl.h> /* for OPENSSL_INIT_(NO_)?LOAD_SSL_STRINGS */
32
#include "crypto/bn.h"
33
#include "crypto/ctype.h"
34
#include "sslerr.h"
35
36
#ifdef S390X_MOD_EXP
37
#include "s390x_arch.h"
38
#endif
39
40
static int stopped = 0;
41
static uint64_t optsdone = 0;
42
43
/* Guards access to the optsdone variable on platforms without atomics */
44
static CRYPTO_RWLOCK *optsdone_lock = NULL;
45
/* Guards simultaneous INIT_LOAD_CONFIG calls with non-NULL settings */
46
static CRYPTO_RWLOCK *init_lock = NULL;
47
static CRYPTO_THREAD_LOCAL in_init_config_local;
48
49
static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT;
50
static int base_inited = 0;
51
static int do_global_cleanup = 0;
52
DEFINE_RUN_ONCE_STATIC(ossl_init_base)
53
1
{
54
    /* no need to init trace */
55
56
1
    OSSL_TRACE(INIT, "ossl_init_base: setting up stop handlers\n");
57
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
58
    ossl_malloc_setup_failures();
59
#endif
60
61
1
    if ((optsdone_lock = CRYPTO_THREAD_lock_new()) == NULL
62
1
        || (init_lock = CRYPTO_THREAD_lock_new()) == NULL)
63
0
        goto err;
64
65
1
    OPENSSL_cpuid_setup();
66
67
1
    if (!ossl_init_thread())
68
0
        goto err;
69
70
1
    if (!CRYPTO_THREAD_init_local(&in_init_config_local, NULL))
71
0
        goto err;
72
73
1
    base_inited = 1;
74
1
    return 1;
75
76
0
err:
77
0
    OSSL_TRACE(INIT, "ossl_init_base failed!\n");
78
0
    CRYPTO_THREAD_lock_free(optsdone_lock);
79
0
    optsdone_lock = NULL;
80
0
    CRYPTO_THREAD_lock_free(init_lock);
81
0
    init_lock = NULL;
82
83
0
    return 0;
84
1
}
85
86
static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT;
87
88
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
89
1
{
90
1
    int ret = 1;
91
    /*
92
     * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
93
     * pulling in all the error strings during static linking
94
     */
95
1
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
96
1
    void *err;
97
98
1
    if (!err_shelve_state(&err))
99
0
        return 0;
100
101
1
    OSSL_TRACE(INIT, "ossl_err_load_crypto_strings()\n");
102
1
    ret = ossl_err_load_crypto_strings();
103
104
1
    err_unshelve_state(err);
105
1
#endif
106
1
    return ret;
107
1
}
108
109
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings,
110
    ossl_init_load_crypto_strings)
111
0
{
112
    /* Do nothing in this case */
113
0
    return 1;
114
0
}
115
116
static CRYPTO_ONCE ssl_strings = CRYPTO_ONCE_STATIC_INIT;
117
118
DEFINE_RUN_ONCE_STATIC(ossl_init_load_ssl_strings)
119
0
{
120
    /*
121
     * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
122
     * pulling in all the error strings during static linking
123
     */
124
0
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
125
0
    OSSL_TRACE(INIT, "ossl_init_load_ssl_strings: ossl_err_load_SSL_strings()\n");
126
0
    ossl_err_load_SSL_strings();
127
0
#endif
128
0
    return 1;
129
0
}
130
131
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_ssl_strings,
132
    ossl_init_load_ssl_strings)
133
0
{
134
    /* Do nothing in this case */
135
0
    return 1;
136
0
}
137
138
static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT;
139
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
140
1
{
141
    /*
142
     * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
143
     * pulling in all the ciphers during static linking
144
     */
145
1
#ifndef OPENSSL_NO_AUTOALGINIT
146
1
    OSSL_TRACE(INIT, "openssl_add_all_ciphers_int()\n");
147
1
    openssl_add_all_ciphers_int();
148
1
#endif
149
1
    return 1;
150
1
}
151
152
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers,
153
    ossl_init_add_all_ciphers)
154
0
{
155
    /* Do nothing */
156
0
    return 1;
157
0
}
158
159
static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT;
160
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
161
1
{
162
    /*
163
     * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
164
     * pulling in all the ciphers during static linking
165
     */
166
1
#ifndef OPENSSL_NO_AUTOALGINIT
167
1
    OSSL_TRACE(INIT, "openssl_add_all_digests()\n");
168
1
    openssl_add_all_digests_int();
169
1
#endif
170
1
    return 1;
171
1
}
172
173
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,
174
    ossl_init_add_all_digests)
175
0
{
176
    /* Do nothing */
177
0
    return 1;
178
0
}
179
180
static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
181
static int config_inited = 0;
182
static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
183
DEFINE_RUN_ONCE_STATIC(ossl_init_config)
184
0
{
185
0
    int ret = ossl_config_int(NULL);
186
187
0
    config_inited = 1;
188
0
    return ret;
189
0
}
190
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_config_settings, ossl_init_config)
191
0
{
192
0
    int ret = ossl_config_int(conf_settings);
193
194
0
    config_inited = 1;
195
0
    return ret;
196
0
}
197
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
198
0
{
199
0
    OSSL_TRACE(INIT, "ossl_no_config_int()\n");
200
0
    ossl_no_config_int();
201
0
    config_inited = 1;
202
0
    return 1;
203
0
}
204
205
static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT;
206
static int async_inited = 0;
207
DEFINE_RUN_ONCE_STATIC(ossl_init_async)
208
0
{
209
0
    OSSL_TRACE(INIT, "async_init()\n");
210
0
    if (!async_init())
211
0
        return 0;
212
0
    async_inited = 1;
213
0
    return 1;
214
0
}
215
216
/*
217
 * Global cleanup function. This is optional, and not strictly
218
 * necessary to run. Operating systems have successfully been
219
 * recovering memory from exiting tasks since the days when I amused
220
 * myself by drawing dinosaurs in crayon on used punch cards.
221
 *
222
 * If we have destructor support, this function is installed and
223
 * always run as a global destructor. It only does anything if
224
 * someone has called OPENSSL_cleanup() before it is run.
225
 *
226
 * This ensures that we do the actual cleanup requested by an
227
 * OPENSSL_cleanup() only after subordinate library destructors which
228
 * may call into OpenSSL have run.
229
 *
230
 * If we do not have destructor support, then this function is not
231
 * normally run, and OPENSSL_cleanup() will do nothing. If we are
232
 * compiled with the compile time define of
233
 * DO_NOT_SKIP_OPENSSL_CLEANUP, this function will be called
234
 * directly from OPENSSL_cleanup() so that cleanup will happen
235
 * when OPENSSL_cleanup() is called.
236
 */
237
void ossl_cleanup_destructor(void)
238
0
{
239
    /*
240
     * At some point we should consider looking at this function with a view to
241
     * moving most/all of this into onfree handlers in OSSL_LIB_CTX.
242
     */
243
244
    /* If we've not been inited then no need to deinit */
245
0
    if (!base_inited)
246
0
        return;
247
248
    /* If we have not been told to clean up, and we are invoked, return */
249
0
    if (!do_global_cleanup)
250
0
        return;
251
252
    /* Might be explicitly called */
253
0
    if (stopped)
254
0
        return;
255
0
    stopped = 1;
256
257
    /*
258
     * Thread stop may not get automatically called by the thread library for
259
     * the very last thread in some situations, so call it directly.
260
     */
261
0
    OPENSSL_thread_stop();
262
263
0
    CRYPTO_THREAD_lock_free(optsdone_lock);
264
0
    optsdone_lock = NULL;
265
0
    CRYPTO_THREAD_lock_free(init_lock);
266
0
    init_lock = NULL;
267
268
0
    CRYPTO_THREAD_cleanup_local(&in_init_config_local);
269
270
    /*
271
     * We assume we are single-threaded for this function, i.e. no race
272
     * conditions for the various "*_inited" vars below.
273
     */
274
275
0
#ifndef OPENSSL_NO_COMP
276
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n");
277
0
    ossl_comp_zlib_cleanup();
278
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_brotli_cleanup()\n");
279
0
    ossl_comp_brotli_cleanup();
280
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zstd_cleanup()\n");
281
0
    ossl_comp_zstd_cleanup();
282
0
#endif
283
284
0
    if (async_inited) {
285
0
        OSSL_TRACE(INIT, "OPENSSL_cleanup: async_deinit()\n");
286
0
        async_deinit();
287
0
    }
288
289
    /*
290
     * Note that cleanup order is important:
291
     * - ossl_rand_cleanup_int could call an ENGINE's RAND cleanup function so
292
     * must be called before engine_cleanup_int()
293
     * - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up
294
     * before the ex data handlers are wiped during default ossl_lib_ctx deinit.
295
     * - ossl_config_modules_free() can end up in ENGINE code so must be called
296
     * before engine_cleanup_int()
297
     * - ENGINEs and additional EVP algorithms might use added OIDs names so
298
     * ossl_obj_cleanup_int() must be called last
299
     */
300
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_rand_cleanup_int()\n");
301
0
    ossl_rand_cleanup_int();
302
303
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_config_modules_free()\n");
304
0
    ossl_config_modules_free();
305
306
0
#ifndef OPENSSL_NO_DEPRECATED_3_0
307
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_store_cleanup_int()\n");
308
0
    ossl_store_cleanup_int();
309
0
#endif
310
311
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_lib_ctx_default_deinit()\n");
312
0
    ossl_lib_ctx_default_deinit();
313
314
0
    ossl_cleanup_thread();
315
316
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: bio_cleanup()\n");
317
0
    bio_cleanup();
318
319
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: evp_cleanup_int()\n");
320
0
    evp_cleanup_int();
321
322
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_obj_cleanup_int()\n");
323
0
    ossl_obj_cleanup_int();
324
325
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: err_int()\n");
326
0
    err_cleanup();
327
328
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: CRYPTO_secure_malloc_done()\n");
329
0
    CRYPTO_secure_malloc_done();
330
331
0
#ifndef OPENSSL_NO_CMP
332
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: OSSL_CMP_log_close()\n");
333
0
    OSSL_CMP_log_close();
334
0
#endif
335
336
0
    OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_trace_cleanup()\n");
337
0
    ossl_trace_cleanup();
338
339
#ifdef S390X_MOD_EXP
340
    OPENSSL_s390x_cleanup();
341
#endif
342
343
0
    base_inited = 0;
344
0
}
345
346
/*
347
 * If this function is called with a non NULL settings value then it must be
348
 * called prior to any threads making calls to any OpenSSL functions,
349
 * i.e. passing a non-null settings value is assumed to be single-threaded.
350
 */
351
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
352
1.27k
{
353
1.27k
    uint64_t tmp;
354
1.27k
    int aloaddone = 0;
355
356
    /* Applications depend on 0 being returned when cleanup was already done */
357
1.27k
    if (ossl_unlikely(stopped)) {
358
0
        if (!(opts & OPENSSL_INIT_BASE_ONLY))
359
0
            ERR_raise(ERR_LIB_CRYPTO, ERR_R_INIT_FAIL);
360
0
        return 0;
361
0
    }
362
363
    /*
364
     * We ignore failures from this function. It is probably because we are
365
     * on a platform that doesn't support lockless atomic loads (we may not
366
     * have created optsdone_lock yet so we can't use it). This is just an
367
     * optimisation to skip the full checks in this function if we don't need
368
     * to, so we carry on regardless in the event of failure.
369
     *
370
     * There could be a race here with other threads, so that optsdone has not
371
     * been updated yet, even though the options have in fact been initialised.
372
     * This doesn't matter - it just means we will run the full function
373
     * unnecessarily - but all the critical code is contained in RUN_ONCE
374
     * functions anyway so we are safe.
375
     */
376
1.27k
    if (ossl_likely(CRYPTO_atomic_load(&optsdone, &tmp, NULL))) {
377
1.27k
        if ((tmp & opts) == opts)
378
0
            return 1;
379
1.27k
        aloaddone = 1;
380
1.27k
    }
381
382
    /*
383
     * At some point we should look at this function with a view to moving
384
     * most/all of this into OSSL_LIB_CTX.
385
     *
386
     * When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the
387
     * *only* option specified.  With that option we return immediately after
388
     * doing the requested limited initialization.
389
     *
390
     * If we remain the only caller of err_shelve_state() the recursion should
391
     * perhaps be removed, but if in doubt, it can be left in place.
392
     */
393
1.27k
    if (ossl_unlikely(!RUN_ONCE(&base, ossl_init_base)))
394
0
        return 0;
395
396
1.27k
    if (opts & OPENSSL_INIT_BASE_ONLY)
397
1.27k
        return 1;
398
399
    /*
400
     * optsdone_lock should definitely be set up now, so we can now repeat the
401
     * same check from above but be sure that it will work even on platforms
402
     * without lockless CRYPTO_atomic_load
403
     */
404
2
    if (!aloaddone) {
405
0
        if (!CRYPTO_atomic_load(&optsdone, &tmp, optsdone_lock))
406
0
            return 0;
407
0
        if ((tmp & opts) == opts)
408
0
            return 1;
409
0
    }
410
411
2
    if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
412
0
        && !RUN_ONCE_ALT(&load_crypto_strings,
413
2
            ossl_init_no_load_crypto_strings,
414
2
            ossl_init_load_crypto_strings))
415
0
        return 0;
416
417
2
    if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
418
1
        && !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings))
419
0
        return 0;
420
421
2
    if ((opts & OPENSSL_INIT_NO_LOAD_SSL_STRINGS)
422
0
        && !RUN_ONCE_ALT(&ssl_strings, ossl_init_no_load_ssl_strings,
423
2
            ossl_init_load_ssl_strings))
424
0
        return 0;
425
426
2
    if ((opts & OPENSSL_INIT_LOAD_SSL_STRINGS)
427
0
        && !RUN_ONCE(&ssl_strings, ossl_init_load_ssl_strings))
428
0
        return 0;
429
430
2
    if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
431
0
        && !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers,
432
2
            ossl_init_add_all_ciphers))
433
0
        return 0;
434
435
2
    if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
436
1
        && !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers))
437
0
        return 0;
438
439
2
    if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
440
0
        && !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests,
441
2
            ossl_init_add_all_digests))
442
0
        return 0;
443
444
2
    if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
445
1
        && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
446
0
        return 0;
447
448
2
    if ((opts & OPENSSL_INIT_ATFORK)
449
0
        && !openssl_init_fork_handlers())
450
0
        return 0;
451
452
2
    if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG)
453
0
        && !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config))
454
0
        return 0;
455
456
2
    if (opts & OPENSSL_INIT_LOAD_CONFIG) {
457
0
        int loading = CRYPTO_THREAD_get_local(&in_init_config_local) != NULL;
458
459
        /* If called recursively from OBJ_ calls, just skip it. */
460
0
        if (!loading) {
461
0
            int ret;
462
463
0
            if (!CRYPTO_THREAD_set_local(&in_init_config_local, (void *)-1))
464
0
                return 0;
465
0
            if (settings == NULL) {
466
0
                ret = RUN_ONCE(&config, ossl_init_config);
467
0
            } else {
468
0
                if (!CRYPTO_THREAD_write_lock(init_lock))
469
0
                    return 0;
470
0
                conf_settings = settings;
471
0
                ret = RUN_ONCE_ALT(&config, ossl_init_config_settings,
472
0
                    ossl_init_config);
473
0
                conf_settings = NULL;
474
0
                CRYPTO_THREAD_unlock(init_lock);
475
0
            }
476
477
0
            if (ret <= 0)
478
0
                return 0;
479
0
        }
480
0
    }
481
482
2
    if ((opts & OPENSSL_INIT_ASYNC)
483
0
        && !RUN_ONCE(&async, ossl_init_async))
484
0
        return 0;
485
486
2
    if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, optsdone_lock))
487
0
        return 0;
488
489
2
    return 1;
490
2
}
491
492
void OPENSSL_cleanup(void)
493
0
{
494
0
    do_global_cleanup = 1;
495
0
#if defined(OSSL_CLEANUP_USING_DESTRUCTOR)
496
0
    return;
497
0
#endif /* defined(OSSL_CLEANUP_USING_DESTRUCTOR) */
498
499
#if defined(DO_NOT_SKIP_OPENSSL_CLEANUP)
500
    ossl_cleanup_destructor();
501
#endif /* defined(DO_NOT_SKIP_OPENSSL_CLEANUP) */
502
0
}