diff options
Diffstat (limited to 'crypto/init.c')
-rw-r--r-- | crypto/init.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/crypto/init.c b/crypto/init.c index 40f3d6e778..7447882c7b 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -19,13 +19,48 @@ */ #include "crypto/init.h" +#include "qemu/thread.h" #ifdef CONFIG_GNUTLS #include <gnutls/gnutls.h> #include <gnutls/crypto.h> +#ifdef CONFIG_GNUTLS_GCRYPT +#include <gcrypt.h> +#endif + /* #define DEBUG_GNUTLS */ +/* + * If GNUTLS is built against GCrypt then + * + * - When GNUTLS >= 2.12, we must not initialize gcrypt threading + * because GNUTLS will do that itself + * - When GNUTLS < 2.12 we must always initialize gcrypt threading + * + * But.... + * + * When gcrypt >= 1.6.0 we must not initialize gcrypt threading + * because gcrypt will do that itself. + * + * So we need to init gcrypt threading if + * + * - gcrypt < 1.6.0 + * AND + * - gnutls < 2.12 + * + */ + +#if (defined(CONFIG_GNUTLS_GCRYPT) && \ + (!defined(GNUTLS_VERSION_NUMBER) || \ + (GNUTLS_VERSION_NUMBER < 0x020c00)) && \ + (!defined(GCRYPT_VERSION_NUMBER) || \ + (GCRYPT_VERSION_NUMBER < 0x010600))) +#define QCRYPTO_INIT_GCRYPT_THREADS +#else +#undef QCRYPTO_INIT_GCRYPT_THREADS +#endif + #ifdef DEBUG_GNUTLS static void qcrypto_gnutls_log(int level, const char *str) { @@ -33,6 +68,49 @@ static void qcrypto_gnutls_log(int level, const char *str) } #endif +#ifdef QCRYPTO_INIT_GCRYPT_THREADS +static int qcrypto_gcrypt_mutex_init(void **priv) +{ \ + QemuMutex *lock = NULL; + lock = g_new0(QemuMutex, 1); + qemu_mutex_init(lock); + *priv = lock; + return 0; +} + +static int qcrypto_gcrypt_mutex_destroy(void **priv) +{ + QemuMutex *lock = *priv; + qemu_mutex_destroy(lock); + g_free(lock); + return 0; +} + +static int qcrypto_gcrypt_mutex_lock(void **priv) +{ + QemuMutex *lock = *priv; + qemu_mutex_lock(lock); + return 0; +} + +static int qcrypto_gcrypt_mutex_unlock(void **priv) +{ + QemuMutex *lock = *priv; + qemu_mutex_unlock(lock); + return 0; +} + +static struct gcry_thread_cbs qcrypto_gcrypt_thread_impl = { + (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)), + NULL, + qcrypto_gcrypt_mutex_init, + qcrypto_gcrypt_mutex_destroy, + qcrypto_gcrypt_mutex_lock, + qcrypto_gcrypt_mutex_unlock, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +#endif /* QCRYPTO_INIT_GCRYPT */ + int qcrypto_init(Error **errp) { int ret; @@ -47,6 +125,18 @@ int qcrypto_init(Error **errp) gnutls_global_set_log_level(10); gnutls_global_set_log_function(qcrypto_gnutls_log); #endif + +#ifdef CONFIG_GNUTLS_GCRYPT + if (!gcry_check_version(GCRYPT_VERSION)) { + error_setg(errp, "Unable to initialize gcrypt"); + return -1; + } +#ifdef QCRYPTO_INIT_GCRYPT_THREADS + gcry_control(GCRYCTL_SET_THREAD_CBS, &qcrypto_gcrypt_thread_impl); +#endif /* QCRYPTO_INIT_GCRYPT_THREADS */ + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); +#endif + return 0; } |