added locking mechanism for multithreaded use of OpenSSL
authorMartin Willi <martin@strongswan.org>
Mon, 3 Nov 2008 16:14:12 +0000 (16:14 -0000)
committerMartin Willi <martin@strongswan.org>
Mon, 3 Nov 2008 16:14:12 +0000 (16:14 -0000)
src/libstrongswan/plugins/openssl/openssl_plugin.c

index d4e0f6f..a159cd5 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <openssl/evp.h>
 #include <openssl/engine.h>
+#include <openssl/crypto.h>
+#include <pthread.h>
 
 #include "openssl_plugin.h"
 
@@ -41,9 +43,120 @@ struct private_openssl_plugin_t {
         * public functions
         */
        openssl_plugin_t public;
+       
+};
+
+/**
+ * Array of static mutexs, with CRYPTO_num_locks() mutex
+ */
+static pthread_mutex_t *mutex;
+
+/**
+ * Locking callback for static locks
+ */
+static void locking_function(int mode, int type, const char *file, int line)
+{
+       if (mode & CRYPTO_LOCK)
+       {
+               pthread_mutex_lock(&mutex[type]);
+       }
+       else
+       {
+               pthread_mutex_unlock(&mutex[type]);
+       }
+}
+
+/**
+ * Implementation of dynlock
+ */
+struct CRYPTO_dynlock_value {
+       pthread_mutex_t mutex;
 };
 
 /**
+ * Callback to create a dynamic lock
+ */
+static struct CRYPTO_dynlock_value *create_function(const char *file, int line)
+{
+       struct CRYPTO_dynlock_value *lock;
+       
+       lock = malloc_thing(struct CRYPTO_dynlock_value);
+       pthread_mutex_init(&lock->mutex, NULL);
+       return lock;
+}
+
+/**
+ * Callback to (un-)lock a dynamic lock
+ */
+static void lock_function(int mode, struct CRYPTO_dynlock_value *lock,
+                                                 const char *file, int line)
+{
+       if (mode & CRYPTO_LOCK)
+       {
+               pthread_mutex_lock(&lock->mutex);
+       }
+       else
+       {
+               pthread_mutex_unlock(&lock->mutex);
+       }
+}
+
+/**
+ * Callback to destroy a dynamic lock
+ */
+static void destroy_function(struct CRYPTO_dynlock_value *lock,
+                                                        const char *file, int line)
+{
+       pthread_mutex_destroy(&lock->mutex);
+       free(lock);
+}
+
+/**
+ * Thread-ID callback function
+ */
+static unsigned long id_function(void)
+{
+       return pthread_self();
+}
+
+/**
+ * initialize OpenSSL for multi-threaded use
+ */
+static void threading_init()
+{
+       int i, num_locks;
+
+       CRYPTO_set_id_callback(id_function);
+       CRYPTO_set_locking_callback(locking_function);
+       
+       CRYPTO_set_dynlock_create_callback(create_function);
+       CRYPTO_set_dynlock_lock_callback(lock_function);
+       CRYPTO_set_dynlock_destroy_callback(destroy_function);
+       
+       num_locks = CRYPTO_num_locks();
+       mutex = malloc(sizeof(pthread_mutex_t) * num_locks);
+       for (i = 0; i < num_locks; i++)
+       {
+               pthread_mutex_init(&mutex[i], NULL);
+       }
+}
+
+/**
+ * cleanup OpenSSL threading locks
+ */
+static void threading_cleanup()
+{
+       int i, num_locks;
+       
+       num_locks = CRYPTO_num_locks();
+       for (i = 0; i < num_locks; i++)
+       {
+               pthread_mutex_destroy(&mutex[i]);
+       }
+       free(mutex);
+}
+
+/**
  * Implementation of openssl_plugin_t.destroy
  */
 static void destroy(private_openssl_plugin_t *this)
@@ -68,6 +181,8 @@ static void destroy(private_openssl_plugin_t *this)
        ENGINE_cleanup();
        EVP_cleanup();
        
+       threading_cleanup();
+       
        free(this);
 }
 
@@ -80,6 +195,8 @@ plugin_t *plugin_create()
        
        this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
        
+       threading_init();
+       
        OpenSSL_add_all_algorithms();
        
        /* activate support for hardware accelerators */