91bfcdb01d
Currently the choice of whether to use nettle or gcrypt is made based on what gnutls is linked to. There are times when it is desirable to be able to force build against a specific library. For example, if testing changes to QEMU's crypto code all 3 possible backends need to be checked regardless of what the local gnutls uses. It is also desirable to be able to enable nettle/gcrypt for cipher/hash algorithms, without enabling gnutls for TLS support. This gives two new configure flags, which allow the following possibilities Automatically determine nettle vs gcrypt from what gnutls links to (recommended to minimize number of crypto libraries linked to) ./configure Automatically determine nettle vs gcrypt based on which is installed ./configure --disable-gnutls Force use of nettle ./configure --enable-nettle Force use of gcrypt ./configure --enable-gcrypt Force use of built-in AES & crippled-DES ./configure --disable-nettle --disable-gcrypt Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
149 lines
3.8 KiB
C
149 lines
3.8 KiB
C
/*
|
|
* QEMU Crypto initialization
|
|
*
|
|
* Copyright (c) 2015 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "crypto/init.h"
|
|
#include "qemu/thread.h"
|
|
|
|
#ifdef CONFIG_GNUTLS
|
|
#include <gnutls/gnutls.h>
|
|
#include <gnutls/crypto.h>
|
|
#endif
|
|
|
|
#ifdef CONFIG_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
|
|
* - When GNUTLS is disabled 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
|
|
* OR
|
|
* - gnutls is disabled
|
|
*
|
|
*/
|
|
|
|
#if (defined(CONFIG_GCRYPT) && \
|
|
(!defined(CONFIG_GNUTLS) || \
|
|
!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)
|
|
{
|
|
fprintf(stderr, "%d: %s", level, 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)
|
|
{
|
|
#ifdef CONFIG_GNUTLS
|
|
int ret;
|
|
ret = gnutls_global_init();
|
|
if (ret < 0) {
|
|
error_setg(errp,
|
|
"Unable to initialize GNUTLS library: %s",
|
|
gnutls_strerror(ret));
|
|
return -1;
|
|
}
|
|
#ifdef DEBUG_GNUTLS
|
|
gnutls_global_set_log_level(10);
|
|
gnutls_global_set_log_function(qcrypto_gnutls_log);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_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;
|
|
}
|