diff options
Diffstat (limited to 'src/threads.c')
-rw-r--r-- | src/threads.c | 222 |
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; } /** |