static void _gnutls_global_deinit(unsigned destructor) { GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); if (_gnutls_init == 1) { _gnutls_init = 0; gnutls_crypto_deinit(); _gnutls_rnd_deinit(); _gnutls_ext_deinit(); asn1_delete_structure(&_gnutls_gnutls_asn); asn1_delete_structure(&_gnutls_pkix1_asn); _gnutls_crypto_deregister(); gnutls_system_global_deinit(); _gnutls_cryptodev_deinit(); #ifdef ENABLE_PKCS11 /* Do not try to deinitialize the PKCS #11 libraries * from the destructor. If we do and the PKCS #11 modules * are already being unloaded, we may crash. */ if (destructor == 0) { gnutls_pkcs11_deinit(); } #endif gnutls_mutex_deinit(&_gnutls_file_mutex); gnutls_mutex_deinit(&_gnutls_pkcs11_mutex); } else { if (_gnutls_init > 0) _gnutls_init--; } GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); }
inline static int _gnutls_rnd_init(void) { if (unlikely(!rnd_initialized)) { int ret; if (_gnutls_rnd_ops.init == NULL) { rnd_initialized = 1; return 0; } if (_gnutls_rnd_ops.init(&gnutls_rnd_ctx) < 0) { gnutls_assert(); return GNUTLS_E_RANDOM_FAILED; } GNUTLS_STATIC_MUTEX_LOCK(gnutls_rnd_ctx_list_mutex); ret = append(gnutls_rnd_ctx); GNUTLS_STATIC_MUTEX_UNLOCK(gnutls_rnd_ctx_list_mutex); if (ret < 0) { gnutls_assert(); _gnutls_rnd_ops.deinit(gnutls_rnd_ctx); return ret; } rnd_initialized = 1; } return 0; }
static void _gnutls_global_deinit(unsigned destructor) { if (!destructor) { GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); } if (_gnutls_init == 1) { _gnutls_init = 0; if (_gnutls_init_ret < 0) { /* only deinitialize if gnutls_global_init() has * succeeded */ gnutls_assert(); goto fail; } _gnutls_system_key_deinit(); gnutls_crypto_deinit(); _gnutls_rnd_deinit(); _gnutls_ext_deinit(); asn1_delete_structure(&_gnutls_gnutls_asn); asn1_delete_structure(&_gnutls_pkix1_asn); _gnutls_crypto_deregister(); gnutls_system_global_deinit(); _gnutls_cryptodev_deinit(); _gnutls_supplemental_deinit(); _gnutls_unload_system_priorities(); #ifdef ENABLE_PKCS11 /* Do not try to deinitialize the PKCS #11 libraries * from the destructor. If we do and the PKCS #11 modules * are already being unloaded, we may crash. */ if (destructor == 0) { gnutls_pkcs11_deinit(); } #endif #ifdef HAVE_TROUSERS _gnutls_tpm_global_deinit(); #endif gnutls_mutex_deinit(&_gnutls_file_mutex); gnutls_mutex_deinit(&_gnutls_pkcs11_mutex); } else { if (_gnutls_init > 0) _gnutls_init--; } fail: if (!destructor) { GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); } }
static int _gnutls_global_init(unsigned constructor) { int ret = 0, res; int level; const char* e; if (!constructor) { GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); } _gnutls_init++; if (_gnutls_init > 1) { if (_gnutls_init == 2 && _gnutls_init_ret == 0) { /* some applications may close the urandom fd * before calling gnutls_global_init(). in that * case reopen it */ ret = _gnutls_rnd_check(); if (ret < 0) { gnutls_assert(); goto out; } } ret = _gnutls_init_ret; goto out; } _gnutls_switch_lib_state(LIB_STATE_INIT); e = secure_getenv("GNUTLS_DEBUG_LEVEL"); if (e != NULL) { level = atoi(e); gnutls_global_set_log_level(level); if (_gnutls_log_func == NULL) gnutls_global_set_log_function(default_log_func); _gnutls_debug_log("Enabled GnuTLS "VERSION" logging...\n"); } #ifdef HAVE_DCGETTEXT bindtextdomain(PACKAGE, LOCALEDIR); #endif res = gnutls_crypto_init(); if (res != 0) { gnutls_assert(); ret = GNUTLS_E_CRYPTO_INIT_FAILED; goto out; } ret = _gnutls_system_key_init(); if (ret != 0) { gnutls_assert(); } /* initialize ASN.1 parser */ if (asn1_check_version(GNUTLS_MIN_LIBTASN1_VERSION) == NULL) { gnutls_assert(); _gnutls_debug_log ("Checking for libtasn1 failed: %s < %s\n", asn1_check_version(NULL), GNUTLS_MIN_LIBTASN1_VERSION); ret = GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY; goto out; } _gnutls_pkix1_asn = ASN1_TYPE_EMPTY; res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL); if (res != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(res); goto out; } res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL); if (res != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(res); goto out; } /* Initialize the random generator */ ret = _gnutls_rnd_preinit(); if (ret < 0) { gnutls_assert(); goto out; } /* Initialize the default TLS extensions */ ret = _gnutls_ext_init(); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_mutex_init(&_gnutls_file_mutex); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_mutex_init(&_gnutls_pkcs11_mutex); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_system_global_init(); if (ret < 0) { gnutls_assert(); goto out; } #ifndef _WIN32 ret = _gnutls_register_fork_handler(); if (ret < 0) { gnutls_assert(); goto out; } #endif #ifdef ENABLE_FIPS140 res = _gnutls_fips_mode_enabled(); /* res == 1 -> fips140-2 mode enabled * res == 2 -> only self checks performed - but no failure * res == not in fips140 mode */ if (res != 0) { _gnutls_debug_log("FIPS140-2 mode: %d\n", res); _gnutls_priority_update_fips(); /* first round of self checks, these are done on the * nettle algorithms which are used internally */ ret = _gnutls_fips_perform_self_checks1(); if (res != 2) { if (ret < 0) { gnutls_assert(); goto out; } } } #endif _gnutls_register_accel_crypto(); _gnutls_cryptodev_init(); _gnutls_load_system_priorities(); #ifdef ENABLE_FIPS140 /* These self tests are performed on the overriden algorithms * (e.g., AESNI overriden AES). They are after _gnutls_register_accel_crypto() * intentionally */ if (res != 0) { ret = _gnutls_fips_perform_self_checks2(); if (res != 2) { if (ret < 0) { gnutls_assert(); goto out; } } _gnutls_fips_mode_reset_zombie(); } #endif _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL); ret = 0; out: _gnutls_init_ret = ret; if (!constructor) { GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); } return ret; }
/** * gnutls_global_init: * * This function performs any required precalculations, detects * the supported CPU capabilities and initializes the underlying * cryptographic backend. In order to free any resources * taken by this call you should gnutls_global_deinit() * when gnutls usage is no longer needed. * * This function increments a global counter, so that * gnutls_global_deinit() only releases resources when it has been * called as many times as gnutls_global_init(). This is useful when * GnuTLS is used by more than one library in an application. This * function can be called many times, but will only do something the * first time. * * Since GnuTLS 3.3.0 this function is only required in systems that * do not support library constructors and static linking. This * function also became thread safe. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_global_init(void) { int ret = 0, res; int level; const char* e; GNUTLS_STATIC_MUTEX_LOCK(global_init_mutex); _gnutls_init++; if (_gnutls_init > 1) { ret = 0; goto out; } _gnutls_switch_lib_state(LIB_STATE_INIT); e = getenv("GNUTLS_DEBUG_LEVEL"); if (e != NULL) { level = atoi(e); gnutls_global_set_log_level(level); if (_gnutls_log_func == NULL) gnutls_global_set_log_function(default_log_func); _gnutls_debug_log("Enabled GnuTLS logging...\n"); } bindtextdomain(PACKAGE, LOCALEDIR); res = gnutls_crypto_init(); if (res != 0) { gnutls_assert(); ret = GNUTLS_E_CRYPTO_INIT_FAILED; goto out; } /* initialize ASN.1 parser */ if (asn1_check_version(GNUTLS_MIN_LIBTASN1_VERSION) == NULL) { gnutls_assert(); _gnutls_debug_log ("Checking for libtasn1 failed: %s < %s\n", asn1_check_version(NULL), GNUTLS_MIN_LIBTASN1_VERSION); ret = GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY; goto out; } res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL); if (res != ASN1_SUCCESS) { ret = _gnutls_asn2err(res); goto out; } res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL); if (res != ASN1_SUCCESS) { ret = _gnutls_asn2err(res); goto out; } /* Initialize the random generator */ ret = _gnutls_rnd_init(); if (ret < 0) { gnutls_assert(); goto out; } /* Initialize the default TLS extensions */ ret = _gnutls_ext_init(); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_mutex_init(&_gnutls_file_mutex); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_mutex_init(&_gnutls_pkcs11_mutex); if (ret < 0) { gnutls_assert(); goto out; } ret = gnutls_system_global_init(); if (ret < 0) { gnutls_assert(); goto out; } _gnutls_register_accel_crypto(); _gnutls_cryptodev_init(); #ifdef ENABLE_FIPS140 /* Perform FIPS140 checks last, so that all modules * have been loaded */ res = _gnutls_fips_mode_enabled(); /* res == 1 -> fips140-2 mode enabled * res == 2 -> only self checks performed - but no failure * res == not in fips140 mode */ if (res != 0) { _gnutls_priority_update_fips(); ret = _gnutls_fips_perform_self_checks(); if (res != 2) { if (ret < 0) { gnutls_assert(); goto out; } } } #endif _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL); ret = 0; out: GNUTLS_STATIC_MUTEX_UNLOCK(global_init_mutex); return ret; }