summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/openssl/openssl_plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/openssl/openssl_plugin.c')
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c104
1 files changed, 81 insertions, 23 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index ce6610ad6..fb34a6858 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2013 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -14,6 +14,7 @@
* for more details.
*/
+#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/rand.h>
@@ -28,6 +29,7 @@
#include <utils/debug.h>
#include <threading/thread.h>
#include <threading/mutex.h>
+#include <threading/thread_value.h>
#include "openssl_util.h"
#include "openssl_crypter.h"
#include "openssl_hasher.h"
@@ -41,10 +43,15 @@
#include "openssl_x509.h"
#include "openssl_crl.h"
#include "openssl_pkcs7.h"
+#include "openssl_pkcs12.h"
#include "openssl_rng.h"
#include "openssl_hmac.h"
#include "openssl_gcm.h"
+#ifndef FIPS_MODE
+#define FIPS_MODE 0
+#endif
+
typedef struct private_openssl_plugin_t private_openssl_plugin_t;
/**
@@ -127,14 +134,51 @@ static void destroy_function(struct CRYPTO_dynlock_value *lock,
}
/**
+ * Thread-local value used to cleanup thread-specific error buffers
+ */
+static thread_value_t *cleanup;
+
+/**
+ * Called when a thread is destroyed. Avoid recursion by setting the thread id
+ * explicitly.
+ */
+static void cleanup_thread(void *arg)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ CRYPTO_THREADID tid;
+
+ CRYPTO_THREADID_set_numeric(&tid, (u_long)(uintptr_t)arg);
+ ERR_remove_thread_state(&tid);
+#else
+ ERR_remove_state((u_long)(uintptr_t)arg);
+#endif
+}
+
+/**
* Thread-ID callback function
*/
-static unsigned long id_function(void)
+static u_long id_function(void)
{
+ u_long id;
+
/* ensure the thread ID is never zero, otherwise OpenSSL might try to
* acquire locks recursively */
- return 1 + (unsigned long)thread_current_id();
+ id = 1 + (u_long)thread_current_id();
+
+ /* cleanup a thread's state later if OpenSSL interacted with it */
+ cleanup->set(cleanup, (void*)(uintptr_t)id);
+ return id;
+}
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+/**
+ * Callback for thread ID
+ */
+static void threadid_function(CRYPTO_THREADID *threadid)
+{
+ CRYPTO_THREADID_set_numeric(threadid, id_function());
}
+#endif /* OPENSSL_VERSION_NUMBER */
/**
* initialize OpenSSL for multi-threaded use
@@ -143,7 +187,14 @@ static void threading_init()
{
int i, num_locks;
+ cleanup = thread_value_create(cleanup_thread);
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+ CRYPTO_THREADID_set_callback(threadid_function);
+#else
CRYPTO_set_id_callback(id_function);
+#endif
+
CRYPTO_set_locking_callback(locking_function);
CRYPTO_set_dynlock_create_callback(create_function);
@@ -159,6 +210,24 @@ static void threading_init()
}
/**
+ * cleanup OpenSSL threading locks
+ */
+static void threading_cleanup()
+{
+ int i, num_locks;
+
+ num_locks = CRYPTO_num_locks();
+ for (i = 0; i < num_locks; i++)
+ {
+ mutex[i]->destroy(mutex[i]);
+ }
+ free(mutex);
+ mutex = NULL;
+
+ cleanup->destroy(cleanup);
+}
+
+/**
* Seed the OpenSSL RNG, if required
*/
static bool seed_rng()
@@ -187,22 +256,6 @@ static bool seed_rng()
return TRUE;
}
-/**
- * cleanup OpenSSL threading locks
- */
-static void threading_cleanup()
-{
- int i, num_locks;
-
- num_locks = CRYPTO_num_locks();
- for (i = 0; i < num_locks; i++)
- {
- mutex[i]->destroy(mutex[i]);
- }
- free(mutex);
- mutex = NULL;
-}
-
METHOD(plugin_t, get_name, char*,
private_openssl_plugin_t *this)
{
@@ -303,6 +356,7 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_192),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_384_384),
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
+ PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_512),
#endif
#endif /* OPENSSL_NO_HMAC */
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
@@ -388,6 +442,8 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS7),
#endif /* OPENSSL_NO_CMS */
#endif /* OPENSSL_VERSION_NUMBER */
+ PLUGIN_REGISTER(CONTAINER_DECODE, openssl_pkcs12_load, TRUE),
+ PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS12),
#ifndef OPENSSL_NO_ECDH
/* EC DH groups */
PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create),
@@ -440,13 +496,15 @@ METHOD(plugin_t, get_features, int,
METHOD(plugin_t, destroy, void,
private_openssl_plugin_t *this)
{
+ CONF_modules_free();
+ OBJ_cleanup();
+ EVP_cleanup();
#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
#endif /* OPENSSL_NO_ENGINE */
- EVP_cleanup();
- CONF_modules_free();
-
+ CRYPTO_cleanup_all_ex_data();
threading_cleanup();
+ ERR_free_strings();
free(this);
}
@@ -470,9 +528,9 @@ plugin_t *openssl_plugin_create()
DBG1(DBG_LIB, "openssl FIPS mode(%d) - %sabled ",fips_mode,
fips_mode ? "en" : "dis");
#else
- DBG1(DBG_LIB, "openssl FIPS mode(%d) unavailable", fips_mode);
if (fips_mode)
{
+ DBG1(DBG_LIB, "openssl FIPS mode(%d) unavailable", fips_mode);
return NULL;
}
#endif