aboutsummaryrefslogtreecommitdiff
path: root/src/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/threads.c')
-rw-r--r--src/threads.c222
1 files changed, 36 insertions, 186 deletions
diff --git a/src/threads.c b/src/threads.c
index 52d437df..792b976d 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -33,213 +33,63 @@
#include "libssh/crypto.h"
#include "libssh/threads.h"
-#ifdef HAVE_LIBMBEDCRYPTO
-#include <mbedtls/threading.h>
-#endif
+static struct ssh_threads_callbacks_struct *user_callbacks = NULL;
-static int threads_noop (void **lock){
- (void)lock;
- return 0;
-}
-
-static unsigned long threads_id_noop (void){
- return 1;
-}
+/** @internal
+ * @brief inits the threading with the backend cryptographic libraries
+ */
-static struct ssh_threads_callbacks_struct ssh_threads_noop =
+int ssh_threads_init(void)
{
- "threads_noop",
- threads_noop,
- threads_noop,
- threads_noop,
- threads_noop,
- threads_id_noop
-};
-
-struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void) {
- return &ssh_threads_noop;
-}
-
-static struct ssh_threads_callbacks_struct *user_callbacks =&ssh_threads_noop;
-
-#ifdef HAVE_LIBGCRYPT
-#if (GCRYPT_VERSION_NUMBER >= 0x010600)
-/* libgcrypt >= 1.6 does not support custom callbacks */
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
-
-static int libgcrypt_thread_init(void){
- if(user_callbacks == NULL)
- return SSH_ERROR;
- if(user_callbacks == &ssh_threads_noop)
- return SSH_OK;
- if (strcmp(user_callbacks->type, "threads_pthread") == 0){
- gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
- return SSH_OK;
- } else {
- /* not supported */
- SSH_LOG(SSH_LOG_WARN, "Custom thread handlers not supported with libgcrypt >=1.6, using pthreads");
- gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
- return SSH_OK;
- }
-}
+ static int threads_initialized = 0;
+ int rc;
-#else
-/* Libgcrypt < 1.6 specific way of handling thread callbacks */
-
-static struct gcry_thread_cbs gcrypt_threads_callbacks;
-
-static int libgcrypt_thread_init(void){
- if(user_callbacks == NULL)
- return SSH_ERROR;
- if(user_callbacks == &ssh_threads_noop){
- gcrypt_threads_callbacks.option= GCRY_THREAD_OPTION_VERSION << 8 || GCRY_THREAD_OPTION_DEFAULT;
- } else {
- gcrypt_threads_callbacks.option= GCRY_THREAD_OPTION_VERSION << 8 || GCRY_THREAD_OPTION_USER;
- }
- gcrypt_threads_callbacks.mutex_init=user_callbacks->mutex_init;
- gcrypt_threads_callbacks.mutex_destroy=user_callbacks->mutex_destroy;
- gcrypt_threads_callbacks.mutex_lock=user_callbacks->mutex_lock;
- gcrypt_threads_callbacks.mutex_unlock=user_callbacks->mutex_unlock;
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcrypt_threads_callbacks);
- return SSH_OK;
-}
-#endif /* GCRYPT_VERSION_NUMBER */
-#elif defined HAVE_LIBMBEDCRYPTO
-static int libmbedcrypto_thread_init(void)
-{
- if (user_callbacks == NULL) {
- return SSH_ERROR;
+ if (threads_initialized) {
+ return SSH_OK;
}
- if (user_callbacks == &ssh_threads_noop) {
- return SSH_OK;
+ /* first initialize the user_callbacks with our default handlers if not
+ * already the case
+ */
+ if (user_callbacks == NULL){
+ user_callbacks = ssh_threads_get_default();
}
-#ifdef MBEDTLS_THREADING_ALT
- else {
- mbedtls_threading_set_alt(user_callbacks->mutex_init,
- user_callbacks->mutex_destroy, user_callbacks->mutex_lock,
- user_callbacks->mutex_unlock);
+
+ /* Then initialize the crypto libraries threading callbacks */
+ rc = crypto_thread_init(user_callbacks);
+ if (rc == SSH_OK) {
+ threads_initialized = 1;
}
-#elif defined MBEDTLS_THREADING_PTHREAD
- return SSH_OK;
-#else
- return SSH_ERROR;
-#endif
+ return rc;
}
-#else /* HAVE_LIBGCRYPT */
-
-/* Libcrypto specific stuff */
-
-static void **libcrypto_mutexes;
-void libcrypto_lock_callback(int mode, int i, const char *file, int line);
-
-void libcrypto_lock_callback(int mode, int i, const char *file, int line)
+void ssh_threads_finalize(void)
{
- (void)file;
- (void)line;
- if(mode & CRYPTO_LOCK){
- user_callbacks->mutex_lock(&libcrypto_mutexes[i]);
- } else {
- user_callbacks->mutex_unlock(&libcrypto_mutexes[i]);
- }
+ crypto_thread_finalize();
}
-#ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK
-static void libcrypto_THREADID_callback(CRYPTO_THREADID *id)
+int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct *cb)
{
- unsigned long thread_id = (*user_callbacks->thread_id)();
-
- CRYPTO_THREADID_set_numeric(id, thread_id);
-}
-#endif /* HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK */
-
-static int libcrypto_thread_init(void){
- int n=CRYPTO_num_locks();
- int i;
- if(user_callbacks == &ssh_threads_noop)
- return SSH_OK;
- libcrypto_mutexes = calloc(n, sizeof(void *));
- if (libcrypto_mutexes == NULL)
- return SSH_ERROR;
- for (i=0;i<n;++i){
- user_callbacks->mutex_init(&libcrypto_mutexes[i]);
- }
-
-#ifdef HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK
- CRYPTO_THREADID_set_callback(libcrypto_THREADID_callback);
-#else
- CRYPTO_set_id_callback(user_callbacks->thread_id);
-#endif
-
- CRYPTO_set_locking_callback(libcrypto_lock_callback);
-
- return SSH_OK;
-}
-static void libcrypto_thread_finalize(void){
- int n=CRYPTO_num_locks();
- int i;
- if (libcrypto_mutexes==NULL)
- return;
- for (i=0;i<n;++i){
- user_callbacks->mutex_destroy(&libcrypto_mutexes[i]);
- }
- SAFE_FREE(libcrypto_mutexes);
+ int rc;
-}
-
-#endif
-
-/** @internal
- * @brief inits the threading with the backend cryptographic libraries
- */
+ if (user_callbacks != NULL) {
+ crypto_thread_finalize();
+ }
-int ssh_threads_init(void){
- static int threads_initialized=0;
- int ret;
- if(threads_initialized)
- return SSH_OK;
- /* first initialize the user_callbacks with our default handlers if not
- * already the case
- */
- if(user_callbacks == NULL){
- user_callbacks=&ssh_threads_noop;
- }
-
- /* Then initialize the crypto libraries threading callbacks */
-#ifdef HAVE_LIBGCRYPT
- ret = libgcrypt_thread_init();
-#elif HAVE_LIBMBEDCRYPTO
- ret = libmbedcrypto_thread_init();
-#else /* Libcrypto */
- ret = libcrypto_thread_init();
-#endif
- if(ret == SSH_OK)
- threads_initialized=1;
- return ret;
-}
+ user_callbacks = cb;
-void ssh_threads_finalize(void){
-#ifdef HAVE_LIBGCRYPT
-#elif HAVE_LIBMBEDCRYPTO
-#ifdef MBEDTLS_THREADING_ALT
- mbedtls_threading_free_alt();
-#endif
-#else
- libcrypto_thread_finalize();
-#endif
-}
+ rc = crypto_thread_init(user_callbacks);
-int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct *cb){
- user_callbacks=cb;
- return SSH_OK;
+ return rc;
}
-const char *ssh_threads_get_type(void) {
- if(user_callbacks != NULL)
- return user_callbacks->type;
- return NULL;
+const char *ssh_threads_get_type(void)
+{
+ if (user_callbacks != NULL) {
+ return user_callbacks->type;
+ }
+ return NULL;
}
/**