aboutsummaryrefslogtreecommitdiff
path: root/crypto/initthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/initthread.c')
-rw-r--r--crypto/initthread.c51
1 files changed, 32 insertions, 19 deletions
diff --git a/crypto/initthread.c b/crypto/initthread.c
index 1bdaeda9fc8e..27b460009e1d 100644
--- a/crypto/initthread.c
+++ b/crypto/initthread.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -12,6 +12,7 @@
#include "crypto/cryptlib.h"
#include "prov/providercommon.h"
#include "internal/thread_once.h"
+#include "crypto/context.h"
#ifdef FIPS_MODULE
#include "prov/provider_ctx.h"
@@ -26,7 +27,7 @@
*
* The FIPS provider tells libcrypto about which threads it is interested in
* by calling "c_thread_start" which is a function pointer created during
- * provider initialisation (i.e. OSSL_init_provider).
+ * provider initialisation (i.e. OSSL_provider_init).
*/
extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
#endif
@@ -248,7 +249,16 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
#else
-static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+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;
CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal));
@@ -256,9 +266,8 @@ static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx)
if (tlocal == NULL)
return NULL;
- if (!CRYPTO_THREAD_init_local(tlocal, NULL)) {
- goto err;
- }
+ if (!CRYPTO_THREAD_init_local(tlocal, NULL))
+ goto deinit;
hands = OPENSSL_zalloc(sizeof(*hands));
if (hands == NULL)
@@ -267,24 +276,31 @@ static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx)
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);
+ CRYPTO_THREAD_cleanup_local(tlocal);
+ deinit:
OPENSSL_free(tlocal);
return NULL;
}
-static void thread_event_ossl_ctx_free(void *tlocal)
+void ossl_thread_event_ctx_free(void *tlocal)
{
+ CRYPTO_THREAD_cleanup_local(tlocal);
OPENSSL_free(tlocal);
}
-static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = {
- OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
- thread_event_ossl_ctx_new,
- thread_event_ossl_ctx_free,
-};
-
static void ossl_arg_thread_stop(void *arg)
{
ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg);
@@ -294,8 +310,7 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
{
THREAD_EVENT_HANDLER **hands;
CRYPTO_THREAD_LOCAL *local
- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX,
- &thread_event_ossl_ctx_method);
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX);
if (local == NULL)
return;
@@ -363,8 +378,7 @@ int ossl_init_thread_start(const void *index, void *arg,
* OSSL_LIB_CTX gets informed about thread stop events individually.
*/
CRYPTO_THREAD_LOCAL *local
- = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX,
- &thread_event_ossl_ctx_method);
+ = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX);
#else
/*
* Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per
@@ -386,8 +400,7 @@ int ossl_init_thread_start(const void *index, void *arg,
* 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