qemu/crypto/init.c
<<
>>
Prefs
   1/*
   2 * QEMU Crypto initialization
   3 *
   4 * Copyright (c) 2015 Red Hat, Inc.
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2.1 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 *
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "crypto/init.h"
  23#include "qapi/error.h"
  24#include "qemu/thread.h"
  25
  26#ifdef CONFIG_GNUTLS
  27#include <gnutls/gnutls.h>
  28#include <gnutls/crypto.h>
  29#endif
  30
  31#ifdef CONFIG_GCRYPT
  32#include <gcrypt.h>
  33#endif
  34
  35#include "crypto/random.h"
  36
  37/* #define DEBUG_GNUTLS */
  38
  39/*
  40 * We need to init gcrypt threading if
  41 *
  42 *   - gcrypt < 1.6.0
  43 *
  44 */
  45
  46#if (defined(CONFIG_GCRYPT) &&                  \
  47     (GCRYPT_VERSION_NUMBER < 0x010600))
  48#define QCRYPTO_INIT_GCRYPT_THREADS
  49#else
  50#undef QCRYPTO_INIT_GCRYPT_THREADS
  51#endif
  52
  53#ifdef DEBUG_GNUTLS
  54static void qcrypto_gnutls_log(int level, const char *str)
  55{
  56    fprintf(stderr, "%d: %s", level, str);
  57}
  58#endif
  59
  60#ifdef QCRYPTO_INIT_GCRYPT_THREADS
  61static int qcrypto_gcrypt_mutex_init(void **priv)
  62{                                                                             \
  63    QemuMutex *lock = NULL;
  64    lock = g_new0(QemuMutex, 1);
  65    qemu_mutex_init(lock);
  66    *priv = lock;
  67    return 0;
  68}
  69
  70static int qcrypto_gcrypt_mutex_destroy(void **priv)
  71{
  72    QemuMutex *lock = *priv;
  73    qemu_mutex_destroy(lock);
  74    g_free(lock);
  75    return 0;
  76}
  77
  78static int qcrypto_gcrypt_mutex_lock(void **priv)
  79{
  80    QemuMutex *lock = *priv;
  81    qemu_mutex_lock(lock);
  82    return 0;
  83}
  84
  85static int qcrypto_gcrypt_mutex_unlock(void **priv)
  86{
  87    QemuMutex *lock = *priv;
  88    qemu_mutex_unlock(lock);
  89    return 0;
  90}
  91
  92static struct gcry_thread_cbs qcrypto_gcrypt_thread_impl = {
  93    (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)),
  94    NULL,
  95    qcrypto_gcrypt_mutex_init,
  96    qcrypto_gcrypt_mutex_destroy,
  97    qcrypto_gcrypt_mutex_lock,
  98    qcrypto_gcrypt_mutex_unlock,
  99    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 100};
 101#endif /* QCRYPTO_INIT_GCRYPT */
 102
 103int qcrypto_init(Error **errp)
 104{
 105#ifdef QCRYPTO_INIT_GCRYPT_THREADS
 106    gcry_control(GCRYCTL_SET_THREAD_CBS, &qcrypto_gcrypt_thread_impl);
 107#endif /* QCRYPTO_INIT_GCRYPT_THREADS */
 108
 109#ifdef CONFIG_GNUTLS
 110    int ret;
 111    ret = gnutls_global_init();
 112    if (ret < 0) {
 113        error_setg(errp,
 114                   "Unable to initialize GNUTLS library: %s",
 115                   gnutls_strerror(ret));
 116        return -1;
 117    }
 118#ifdef DEBUG_GNUTLS
 119    gnutls_global_set_log_level(10);
 120    gnutls_global_set_log_function(qcrypto_gnutls_log);
 121#endif
 122#endif
 123
 124#ifdef CONFIG_GCRYPT
 125    if (!gcry_check_version(GCRYPT_VERSION)) {
 126        error_setg(errp, "Unable to initialize gcrypt");
 127        return -1;
 128    }
 129    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
 130#endif
 131
 132    if (qcrypto_random_init(errp) < 0) {
 133        return -1;
 134    }
 135
 136    return 0;
 137}
 138