#else
+static void ossl_arg_thread_stop(void *arg);
+
+/* Register the current thread so that we are informed if it gets stopped */
+int ossl_thread_register_fips(OSSL_LIB_CTX *libctx)
+{
+ return c_thread_start(FIPS_get_core_handle(libctx), ossl_arg_thread_stop,
+ libctx);
+}
+
void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *libctx)
{
THREAD_EVENT_HANDLER **hands = NULL;
if (!CRYPTO_THREAD_set_local(tlocal, hands))
goto err;
+ /*
+ * We should ideally call ossl_thread_register_fips() here. This function
+ * is called during the startup of the FIPS provider and we need to ensure
+ * that the main thread is registered to receive thread callbacks in order
+ * to free |hands| that we allocated above. However we are too early in
+ * the FIPS provider initialisation that FIPS_get_core_handle() doesn't work
+ * yet. So we defer this to the main provider OSSL_provider_init_int()
+ * function.
+ */
+
return tlocal;
err:
OPENSSL_free(hands);
* libcrypto to tell us about later thread stop events. c_thread_start
* is a callback to libcrypto defined in fipsprov.c
*/
- if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop,
- ctx))
+ if (!ossl_thread_register_fips(ctx))
return 0;
}
#endif
void *ossl_prov_drbg_nonce_ctx_new(OSSL_LIB_CTX *);
void *ossl_self_test_set_callback_new(OSSL_LIB_CTX *);
void *ossl_rand_crng_ctx_new(OSSL_LIB_CTX *);
+int ossl_thread_register_fips(OSSL_LIB_CTX *);
void *ossl_thread_event_ctx_new(OSSL_LIB_CTX *);
void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *);
#if defined(OPENSSL_THREADS)
fgbl->handle = handle;
+ /*
+ * We need to register this thread to receive thread lifecycle callbacks.
+ * This wouldn't matter if the current thread is also the same thread that
+ * closes the FIPS provider down. But if that happens on a different thread
+ * then memory leaks could otherwise occur.
+ */
+ if (!ossl_thread_register_fips(libctx))
+ goto err;
+
/*
* We did initial set up of selftest_params in a local copy, because we
* could not create fgbl until c_CRYPTO_zalloc was defined in the loop