summaryrefslogtreecommitdiffstats
path: root/include/internal
diff options
context:
space:
mode:
authorČestmír Kalina <ckalina@redhat.com>2021-09-27 22:42:11 +0200
committerMatt Caswell <matt@openssl.org>2022-10-17 09:45:39 +0100
commit4574a7fd8dda070b129d76defca07703cab53842 (patch)
treea6e03446b0f784e550010a2c51efe5b7861e9473 /include/internal
parentb1372197496650c3cb318cade911a3bd6af14adc (diff)
crypto: add preemptive threading support
Some primitives are designed to be used in a multi-threaded environment, if supported, e.g., Argon2. This patch adds support for preemptive threading and basic synchronization primitives for platforms compliant with POSIX threads or Windows CRT. Native functions are wrapped to provide a common (internal) API. Threading support can be disabled at compile time. If enabled, threading is disabled by default and needs to be explicitly enabled by the user. Thread enablement requires an explicit limit on the number of threads that OpenSSL may spawn (non-negative integer/infinity). The limit may be changed. Signed-off-by: Čestmír Kalina <ckalina@redhat.com> Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/12255)
Diffstat (limited to 'include/internal')
-rw-r--r--include/internal/cryptlib.h3
-rw-r--r--include/internal/thread.h39
-rw-r--r--include/internal/thread_arch.h119
3 files changed, 160 insertions, 1 deletions
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 71b6b125f3..700f387531 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -116,7 +116,8 @@ typedef struct ossl_ex_data_global_st {
# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX 16
# define OSSL_LIB_CTX_BIO_CORE_INDEX 17
# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18
-# define OSSL_LIB_CTX_MAX_INDEXES 19
+# define OSSL_LIB_CTX_THREAD_INDEX 19
+# define OSSL_LIB_CTX_MAX_INDEXES 20
OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx);
diff --git a/include/internal/thread.h b/include/internal/thread.h
new file mode 100644
index 0000000000..8c5bad7763
--- /dev/null
+++ b/include/internal/thread.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019-2021 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OPENSSL_INTERNAL_THREAD_H
+# define OPENSSL_INTERNAL_THREAD_H
+# include <openssl/configuration.h>
+# include <internal/thread_arch.h>
+# include <openssl/e_os2.h>
+# include <openssl/types.h>
+# include <internal/cryptlib.h>
+# include "crypto/context.h"
+
+void *ossl_crypto_thread_start(OSSL_LIB_CTX *ctx, CRYPTO_THREAD_ROUTINE start,
+ void *data);
+int ossl_crypto_thread_join(void *task, CRYPTO_THREAD_RETVAL *retval);
+int ossl_crypto_thread_clean(void *vhandle);
+uint64_t ossl_get_avail_threads(OSSL_LIB_CTX *ctx);
+
+# if defined(OPENSSL_THREADS)
+
+# define OSSL_LIB_CTX_GET_THREADS(CTX) \
+ ossl_lib_ctx_get_data(CTX, OSSL_LIB_CTX_THREAD_INDEX);
+
+typedef struct openssl_threads_st {
+ uint64_t max_threads;
+ uint64_t active_threads;
+ CRYPTO_MUTEX *lock;
+ CRYPTO_CONDVAR *cond_finished;
+} OSSL_LIB_CTX_THREADS;
+
+# endif /* defined(OPENSSL_THREADS) */
+
+#endif /* OPENSSL_INTERNAL_THREAD_H */
diff --git a/include/internal/thread_arch.h b/include/internal/thread_arch.h
new file mode 100644
index 0000000000..fcf312ff14
--- /dev/null
+++ b/include/internal/thread_arch.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2019-2021 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
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_THREAD_ARCH_H
+# define OSSL_INTERNAL_THREAD_ARCH_H
+# include <openssl/configuration.h>
+# include <openssl/e_os2.h>
+
+# if defined(_WIN32)
+# include <windows.h>
+# endif
+
+# if defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_UNIX)
+# define OPENSSL_THREADS_POSIX
+# elif defined(OPENSSL_THREADS) && defined(OPENSSL_SYS_WINDOWS) && \
+ defined(_WIN32_WINNT)
+# if _WIN32_WINNT >= 0x0600
+# define OPENSSL_THREADS_WINNT
+# else
+# define OPENSSL_THREADS_NONE
+# endif
+# else
+# define OPENSSL_THREADS_NONE
+# endif
+
+# include <openssl/crypto.h>
+
+typedef void CRYPTO_MUTEX;
+typedef void CRYPTO_CONDVAR;
+
+CRYPTO_MUTEX *ossl_crypto_mutex_new(void);
+void ossl_crypto_mutex_lock(CRYPTO_MUTEX *mutex);
+int ossl_crypto_mutex_try_lock(CRYPTO_MUTEX *mutex);
+void ossl_crypto_mutex_unlock(CRYPTO_MUTEX *mutex);
+void ossl_crypto_mutex_free(CRYPTO_MUTEX **mutex);
+
+CRYPTO_CONDVAR *ossl_crypto_condvar_new(void);
+void ossl_crypto_condvar_wait(CRYPTO_CONDVAR *cv, CRYPTO_MUTEX *mutex);
+void ossl_crypto_condvar_broadcast(CRYPTO_CONDVAR *cv);
+void ossl_crypto_condvar_free(CRYPTO_CONDVAR **cv);
+
+typedef uint32_t CRYPTO_THREAD_RETVAL;
+typedef CRYPTO_THREAD_RETVAL (*CRYPTO_THREAD_ROUTINE)(void *);
+typedef CRYPTO_THREAD_RETVAL (*CRYPTO_THREAD_ROUTINE_CB)(void *,
+ void (**)(void *),
+ void **);
+
+# define CRYPTO_THREAD_NO_STATE 0UL
+# define CRYPTO_THREAD_FINISHED (1UL << 1)
+# define CRYPTO_THREAD_JOINED (1UL << 2)
+# define CRYPTO_THREAD_TERMINATED (1UL << 3)
+
+# define CRYPTO_THREAD_GET_STATE(THREAD, FLAG) ((THREAD)->state & (FLAG))
+# define CRYPTO_THREAD_GET_ERROR(THREAD, FLAG) (((THREAD)->state >> 16) & (FLAG))
+
+typedef struct crypto_thread_st {
+ uint32_t state;
+ void *data;
+ CRYPTO_THREAD_ROUTINE routine;
+ CRYPTO_THREAD_RETVAL retval;
+ void *handle;
+ CRYPTO_MUTEX *lock;
+ CRYPTO_MUTEX *statelock;
+ CRYPTO_CONDVAR *condvar;
+ unsigned long thread_id;
+ int joinable;
+ OSSL_LIB_CTX *ctx;
+} CRYPTO_THREAD;
+
+# if defined(OPENSSL_THREADS)
+
+# define CRYPTO_THREAD_UNSET_STATE(THREAD, FLAG) \
+ do { \
+ (THREAD)->state &= ~(FLAG); \
+ } while ((void)0, 0)
+
+# define CRYPTO_THREAD_SET_STATE(THREAD, FLAG) \
+ do { \
+ (THREAD)->state |= (FLAG); \
+ } while ((void)0, 0)
+
+# define CRYPTO_THREAD_SET_ERROR(THREAD, FLAG) \
+ do { \
+ (THREAD)->state |= ((FLAG) << 16); \
+ } while ((void)0, 0)
+
+# define CRYPTO_THREAD_UNSET_ERROR(THREAD, FLAG) \
+ do { \
+ (THREAD)->state &= ~((FLAG) << 16); \
+ } while ((void)0, 0)
+
+# else
+
+# define CRYPTO_THREAD_UNSET_STATE(THREAD, FLAG)
+# define CRYPTO_THREAD_SET_STATE(THREAD, FLAG)
+# define CRYPTO_THREAD_SET_ERROR(THREAD, FLAG)
+# define CRYPTO_THREAD_UNSET_ERROR(THREAD, FLAG)
+
+# endif /* defined(OPENSSL_THREADS) */
+
+CRYPTO_THREAD * ossl_crypto_thread_native_start(CRYPTO_THREAD_ROUTINE routine,
+ void *data, int joinable);
+int ossl_crypto_thread_native_spawn(CRYPTO_THREAD *thread);
+int ossl_crypto_thread_native_join(CRYPTO_THREAD *thread,
+ CRYPTO_THREAD_RETVAL *retval);
+int ossl_crypto_thread_native_terminate(CRYPTO_THREAD *thread);
+int ossl_crypto_thread_native_exit(void);
+int ossl_crypto_thread_native_is_self(CRYPTO_THREAD *thread);
+int ossl_crypto_thread_native_clean(CRYPTO_THREAD *thread);
+
+void ossl_crypto_mem_barrier(void);
+
+#endif /* OSSL_INTERNAL_THREAD_ARCH_H */