/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2020 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
*/
#include <openssl/crypto.h>
-#include <openssl/core_numbers.h>
-#include "internal/cryptlib_int.h"
-#include "internal/providercommon.h"
+#include <openssl/core_dispatch.h>
+#include "crypto/cryptlib.h"
+#include "prov/providercommon.h"
#include "internal/thread_once.h"
-#ifdef FIPS_MODE
+#ifdef FIPS_MODULE
/*
* Thread aware code may want to be told about thread stop events. We register
* to hear about those thread stop events when we see a new thread has started.
THREAD_EVENT_HANDLER *next;
};
-#ifndef FIPS_MODE
+#ifndef FIPS_MODULE
DEFINE_SPECIAL_STACK_OF(THREAD_EVENT_HANDLER_PTR, THREAD_EVENT_HANDLER *)
typedef struct global_tevent_register_st GLOBAL_TEVENT_REGISTER;
}
#endif
+#ifndef FIPS_MODULE
+static int init_thread_push_handlers(THREAD_EVENT_HANDLER **hands);
+static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin);
+static void init_thread_destructor(void *hands);
+static int init_thread_deregister(void *arg, int all);
+#endif
static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands);
static THREAD_EVENT_HANDLER **
if (alloc) {
if (hands == NULL) {
-#ifndef FIPS_MODE
- GLOBAL_TEVENT_REGISTER *gtr;
-#endif
- if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL) {
- OPENSSL_free(hands);
+ if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL)
return NULL;
- }
-#ifndef FIPS_MODE
- /*
- * The thread event handler is thread specific and is a linked
- * list of all handler functions that should be called for the
- * current thread. We also keep a global reference to that linked
- * list, so that we can deregister handlers if necessary before all
- * the threads are stopped.
- */
- gtr = get_global_tevent_register();
- if (gtr == NULL) {
+ if (!CRYPTO_THREAD_set_local(local, hands)) {
OPENSSL_free(hands);
return NULL;
}
- CRYPTO_THREAD_write_lock(gtr->lock);
- if (!sk_THREAD_EVENT_HANDLER_PTR_push(gtr->skhands, hands)) {
+
+#ifndef FIPS_MODULE
+ if (!init_thread_push_handlers(hands)) {
+ CRYPTO_THREAD_set_local(local, NULL);
OPENSSL_free(hands);
- CRYPTO_THREAD_unlock(gtr->lock);
return NULL;
}
- CRYPTO_THREAD_unlock(gtr->lock);
#endif
- if (!CRYPTO_THREAD_set_local(local, hands)) {
- OPENSSL_free(hands);
- return NULL;
- }
}
} else if (!keep) {
CRYPTO_THREAD_set_local(local, NULL);
return hands;
}
-#ifndef FIPS_MODE
+#ifndef FIPS_MODULE
/*
* Since per-thread-specific-data destructors are not universally
* available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key
CRYPTO_THREAD_LOCAL value;
} destructor_key = { -1 };
+/*
+ * The thread event handler list is a thread specific linked list
+ * of callback functions which are invoked in list order by the
+ * current thread in case of certain events. (Currently, there is
+ * only one type of event, the 'thread stop' event.)
+ *
+ * We also keep a global reference to that linked list, so that we
+ * can deregister handlers if necessary before all the threads are
+ * stopped.
+ */
+static int init_thread_push_handlers(THREAD_EVENT_HANDLER **hands)
+{
+ int ret;
+ GLOBAL_TEVENT_REGISTER *gtr;
+
+ gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return 0;
+
+ CRYPTO_THREAD_write_lock(gtr->lock);
+ ret = (sk_THREAD_EVENT_HANDLER_PTR_push(gtr->skhands, hands) != 0);
+ CRYPTO_THREAD_unlock(gtr->lock);
+
+ return ret;
+}
+
static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin)
{
GLOBAL_TEVENT_REGISTER *gtr;
return 1;
}
-static int init_thread_deregister(void *arg, int all);
-
void ossl_cleanup_thread(void)
{
init_thread_deregister(NULL, 1);
init_thread_stop(arg, hands);
OPENSSL_free(hands);
}
-#endif /* FIPS_MODE */
+#endif /* FIPS_MODULE */
static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands)
{
- THREAD_EVENT_HANDLER *curr, *prev = NULL;
+ THREAD_EVENT_HANDLER *curr, *prev = NULL, *tmp;
/* Can't do much about this */
if (hands == NULL)
curr = *hands;
while (curr != NULL) {
if (arg != NULL && curr->arg != arg) {
+ prev = curr;
curr = curr->next;
continue;
}
curr->handfn(curr->arg);
- prev = curr;
+ if (prev == NULL)
+ *hands = curr->next;
+ else
+ prev->next = curr->next;
+
+ tmp = curr;
curr = curr->next;
- if (prev == *hands)
- *hands = curr;
- OPENSSL_free(prev);
+
+ OPENSSL_free(tmp);
}
}
{
THREAD_EVENT_HANDLER **hands;
THREAD_EVENT_HANDLER *hand;
-#ifdef FIPS_MODE
+#ifdef FIPS_MODULE
OPENSSL_CTX *ctx = arg;
/*
if (hands == NULL)
return 0;
-#ifdef FIPS_MODE
+#ifdef FIPS_MODULE
if (*hands == NULL) {
/*
* We've not yet registered any handlers for this thread. We need to get
* 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_provider(ctx), ossl_ctx_thread_stop))
+ if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_ctx_thread_stop))
return 0;
}
#endif
return 1;
}
-#ifndef FIPS_MODE
+#ifndef FIPS_MODULE
static int init_thread_deregister(void *index, int all)
{
GLOBAL_TEVENT_REGISTER *gtr;
int i;
gtr = get_global_tevent_register();
+ if (gtr == NULL)
+ return 0;
if (!all)
CRYPTO_THREAD_write_lock(gtr->lock);
for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) {