Branch data Line data Source code
1 : : /* 2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 : : * 4 : : * Licensed under the Apache License, Version 2.0 (the "License"). 5 : : * You may not use this file except in compliance with the License. 6 : : * A copy of the License is located at 7 : : * 8 : : * http://aws.amazon.com/apache2.0 9 : : * 10 : : * or in the "license" file accompanying this file. This file is distributed 11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 : : * express or implied. See the License for the specific language governing 13 : : * permissions and limitations under the License. 14 : : */ 15 : : 16 : : #include "utils/s2n_init.h" 17 : : 18 : : #include <pthread.h> 19 : : 20 : : #include "api/unstable/cleanup.h" 21 : : #include "crypto/s2n_fips.h" 22 : : #include "crypto/s2n_libcrypto.h" 23 : : #include "crypto/s2n_locking.h" 24 : : #include "error/s2n_errno.h" 25 : : #include "openssl/opensslv.h" 26 : : #include "tls/extensions/s2n_client_key_share.h" 27 : : #include "tls/extensions/s2n_extension_type.h" 28 : : #include "tls/s2n_cipher_suites.h" 29 : : #include "tls/s2n_security_policies.h" 30 : : #include "tls/s2n_tls13_secrets.h" 31 : : #include "utils/s2n_mem.h" 32 : : #include "utils/s2n_random.h" 33 : : #include "utils/s2n_safety.h" 34 : : #include "utils/s2n_safety_macros.h" 35 : : 36 : : static void s2n_cleanup_atexit(void); 37 : : 38 : : static pthread_t main_thread = 0; 39 : : static bool initialized = false; 40 : : static bool atexit_cleanup = false; 41 : : int s2n_disable_atexit(void) 42 : 0 : { 43 [ # # ][ # # ]: 0 : POSIX_ENSURE(!initialized, S2N_ERR_INITIALIZED); 44 : 0 : atexit_cleanup = false; 45 : 0 : return S2N_SUCCESS; 46 : 0 : } 47 : : 48 : : int s2n_enable_atexit(void) 49 : 522 : { 50 : 522 : atexit_cleanup = true; 51 : 522 : return S2N_SUCCESS; 52 : 522 : } 53 : : 54 : : int s2n_init(void) 55 : 549 : { 56 : : /* USAGE-GUIDE says s2n_init MUST NOT be called more than once 57 : : * Public documentation for API states s2n_init should only be called once 58 : : * https://github.com/aws/s2n-tls/issues/3446 is a result of not enforcing this 59 : : */ 60 [ + - ][ + + ]: 549 : POSIX_ENSURE(!initialized, S2N_ERR_INITIALIZED); 61 : : 62 : 545 : main_thread = pthread_self(); 63 : : 64 [ - + ]: 545 : if (getenv("S2N_INTEG_TEST")) { 65 [ # # ]: 0 : POSIX_GUARD(s2n_in_integ_test_set(true)); 66 : 0 : } 67 : : 68 : : /* Should run before any init method that calls libcrypto methods 69 : : * to ensure we don't try to call methods that don't exist. 70 : : * It doesn't require any locks since it only deals with values that 71 : : * should be constant, so can run before s2n_locking_init. */ 72 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_libcrypto_validate_runtime()); 73 : : /* Must run before any init method that allocates memory. */ 74 [ - + ]: 545 : POSIX_GUARD(s2n_mem_init()); 75 : : /* Must run before any init method that calls libcrypto methods. */ 76 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_locking_init()); 77 [ - + ]: 545 : POSIX_GUARD(s2n_fips_init()); 78 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_rand_init()); 79 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_hash_algorithms_init()); 80 [ - + ]: 545 : POSIX_GUARD(s2n_cipher_suites_init()); 81 [ - + ]: 545 : POSIX_GUARD(s2n_security_policies_init()); 82 [ - + ]: 545 : POSIX_GUARD(s2n_config_defaults_init()); 83 [ - + ]: 545 : POSIX_GUARD(s2n_extension_type_init()); 84 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_tls13_empty_transcripts_init()); 85 [ - + ]: 545 : POSIX_GUARD_RESULT(s2n_atomic_init()); 86 : : 87 [ + - ]: 545 : if (atexit_cleanup) { 88 [ - + ][ # # ]: 545 : POSIX_ENSURE_OK(atexit(s2n_cleanup_atexit), S2N_ERR_ATEXIT); 89 : 545 : } 90 : : 91 [ - + ]: 545 : if (getenv("S2N_PRINT_STACKTRACE")) { 92 : 0 : s2n_stack_traces_enabled_set(true); 93 : 0 : } 94 : : 95 : : #if defined(OPENSSL_IS_AWSLC) 96 : : CRYPTO_pre_sandbox_init(); 97 : : #endif 98 : : 99 : 545 : initialized = true; 100 : : 101 : 545 : return S2N_SUCCESS; 102 : 545 : } 103 : : 104 : : static bool s2n_cleanup_atexit_impl(void) 105 : 576 : { 106 : : /* all of these should run, regardless of result, but the 107 : : * values to need to be consumed to prevent warnings */ 108 : : 109 : : /* the configs need to be wiped before resetting the memory callbacks */ 110 : 576 : s2n_wipe_static_configs(); 111 : : 112 [ + - ]: 576 : bool cleaned_up = s2n_result_is_ok(s2n_cipher_suites_cleanup()) 113 [ + - ]: 576 : && s2n_result_is_ok(s2n_hash_algorithms_cleanup()) 114 [ + - ]: 576 : && s2n_result_is_ok(s2n_rand_cleanup_thread()) 115 [ + + ]: 576 : && s2n_result_is_ok(s2n_rand_cleanup()) 116 [ + - ]: 576 : && s2n_result_is_ok(s2n_locking_cleanup()) 117 [ + - ]: 576 : && (s2n_mem_cleanup() == S2N_SUCCESS); 118 : : 119 : 576 : initialized = !cleaned_up; 120 : 576 : return cleaned_up; 121 : 576 : } 122 : : 123 : : int s2n_cleanup_thread(void) 124 : 303 : { 125 : : /* s2n_cleanup_thread is supposed to be called from each thread before exiting, 126 : : * so ensure that whatever clean ups we have here are thread safe */ 127 [ - + ]: 303 : POSIX_GUARD_RESULT(s2n_rand_cleanup_thread()); 128 : 303 : return S2N_SUCCESS; 129 : 303 : } 130 : : 131 : : int s2n_cleanup_final(void) 132 : 34 : { 133 : : /* some cleanups are not idempotent (rand_cleanup, mem_cleanup) so protect */ 134 [ + + ][ + - ]: 34 : POSIX_ENSURE(initialized, S2N_ERR_NOT_INITIALIZED); 135 [ - + ][ # # ]: 31 : POSIX_ENSURE(s2n_cleanup_atexit_impl(), S2N_ERR_ATEXIT); 136 : : 137 : 31 : return S2N_SUCCESS; 138 : 31 : } 139 : : 140 : : int s2n_cleanup(void) 141 : 300 : { 142 [ - + ]: 300 : POSIX_GUARD(s2n_cleanup_thread()); 143 : : 144 : 300 : return S2N_SUCCESS; 145 : 300 : } 146 : : 147 : : static void s2n_cleanup_atexit(void) 148 : 545 : { 149 : 545 : (void) s2n_cleanup_atexit_impl(); 150 : 545 : } 151 : : 152 : : bool s2n_is_initialized(void) 153 : 4153 : { 154 : 4153 : return initialized; 155 : 4153 : }