qemu/crypto/tlscreds.c
<<
>>
Prefs
   1/*
   2 * QEMU crypto TLS credential support
   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 "qapi/error.h"
  23#include "qemu/module.h"
  24#include "tlscredspriv.h"
  25#include "trace.h"
  26
  27#define DH_BITS 2048
  28
  29#ifdef CONFIG_GNUTLS
  30int
  31qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
  32                                     const char *filename,
  33                                     gnutls_dh_params_t *dh_params,
  34                                     Error **errp)
  35{
  36    int ret;
  37
  38    trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");
  39
  40    if (filename == NULL) {
  41        ret = gnutls_dh_params_init(dh_params);
  42        if (ret < 0) {
  43            error_setg(errp, "Unable to initialize DH parameters: %s",
  44                       gnutls_strerror(ret));
  45            return -1;
  46        }
  47        ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
  48        if (ret < 0) {
  49            gnutls_dh_params_deinit(*dh_params);
  50            *dh_params = NULL;
  51            error_setg(errp, "Unable to generate DH parameters: %s",
  52                       gnutls_strerror(ret));
  53            return -1;
  54        }
  55    } else {
  56        GError *gerr = NULL;
  57        gchar *contents;
  58        gsize len;
  59        gnutls_datum_t data;
  60        if (!g_file_get_contents(filename,
  61                                 &contents,
  62                                 &len,
  63                                 &gerr)) {
  64
  65            error_setg(errp, "%s", gerr->message);
  66            g_error_free(gerr);
  67            return -1;
  68        }
  69        data.data = (unsigned char *)contents;
  70        data.size = len;
  71        ret = gnutls_dh_params_init(dh_params);
  72        if (ret < 0) {
  73            g_free(contents);
  74            error_setg(errp, "Unable to initialize DH parameters: %s",
  75                       gnutls_strerror(ret));
  76            return -1;
  77        }
  78        ret = gnutls_dh_params_import_pkcs3(*dh_params,
  79                                            &data,
  80                                            GNUTLS_X509_FMT_PEM);
  81        g_free(contents);
  82        if (ret < 0) {
  83            gnutls_dh_params_deinit(*dh_params);
  84            *dh_params = NULL;
  85            error_setg(errp, "Unable to load DH parameters from %s: %s",
  86                       filename, gnutls_strerror(ret));
  87            return -1;
  88        }
  89    }
  90
  91    return 0;
  92}
  93
  94
  95int
  96qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
  97                           const char *filename,
  98                           bool required,
  99                           char **cred,
 100                           Error **errp)
 101{
 102    struct stat sb;
 103    int ret = -1;
 104
 105    if (!creds->dir) {
 106        if (required) {
 107            error_setg(errp, "Missing 'dir' property value");
 108            return -1;
 109        } else {
 110            return 0;
 111        }
 112    }
 113
 114    *cred = g_strdup_printf("%s/%s", creds->dir, filename);
 115
 116    if (stat(*cred, &sb) < 0) {
 117        if (errno == ENOENT && !required) {
 118            ret = 0;
 119        } else {
 120            error_setg_errno(errp, errno,
 121                             "Unable to access credentials %s",
 122                             *cred);
 123        }
 124        g_free(*cred);
 125        *cred = NULL;
 126        goto cleanup;
 127    }
 128
 129    ret = 0;
 130 cleanup:
 131    trace_qcrypto_tls_creds_get_path(creds, filename,
 132                                     *cred ? *cred : "<none>");
 133    return ret;
 134}
 135
 136
 137#endif /* ! CONFIG_GNUTLS */
 138
 139
 140static void
 141qcrypto_tls_creds_prop_set_verify(Object *obj,
 142                                  bool value,
 143                                  Error **errp G_GNUC_UNUSED)
 144{
 145    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 146
 147    creds->verifyPeer = value;
 148}
 149
 150
 151static bool
 152qcrypto_tls_creds_prop_get_verify(Object *obj,
 153                                  Error **errp G_GNUC_UNUSED)
 154{
 155    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 156
 157    return creds->verifyPeer;
 158}
 159
 160
 161static void
 162qcrypto_tls_creds_prop_set_dir(Object *obj,
 163                               const char *value,
 164                               Error **errp G_GNUC_UNUSED)
 165{
 166    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 167
 168    creds->dir = g_strdup(value);
 169}
 170
 171
 172static char *
 173qcrypto_tls_creds_prop_get_dir(Object *obj,
 174                               Error **errp G_GNUC_UNUSED)
 175{
 176    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 177
 178    return g_strdup(creds->dir);
 179}
 180
 181
 182static void
 183qcrypto_tls_creds_prop_set_priority(Object *obj,
 184                                    const char *value,
 185                                    Error **errp G_GNUC_UNUSED)
 186{
 187    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 188
 189    creds->priority = g_strdup(value);
 190}
 191
 192
 193static char *
 194qcrypto_tls_creds_prop_get_priority(Object *obj,
 195                                    Error **errp G_GNUC_UNUSED)
 196{
 197    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 198
 199    return g_strdup(creds->priority);
 200}
 201
 202
 203static void
 204qcrypto_tls_creds_prop_set_endpoint(Object *obj,
 205                                    int value,
 206                                    Error **errp G_GNUC_UNUSED)
 207{
 208    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 209
 210    creds->endpoint = value;
 211}
 212
 213
 214static int
 215qcrypto_tls_creds_prop_get_endpoint(Object *obj,
 216                                    Error **errp G_GNUC_UNUSED)
 217{
 218    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 219
 220    return creds->endpoint;
 221}
 222
 223
 224static void
 225qcrypto_tls_creds_class_init(ObjectClass *oc, void *data)
 226{
 227    object_class_property_add_bool(oc, "verify-peer",
 228                                   qcrypto_tls_creds_prop_get_verify,
 229                                   qcrypto_tls_creds_prop_set_verify,
 230                                   NULL);
 231    object_class_property_add_str(oc, "dir",
 232                                  qcrypto_tls_creds_prop_get_dir,
 233                                  qcrypto_tls_creds_prop_set_dir,
 234                                  NULL);
 235    object_class_property_add_enum(oc, "endpoint",
 236                                   "QCryptoTLSCredsEndpoint",
 237                                   &QCryptoTLSCredsEndpoint_lookup,
 238                                   qcrypto_tls_creds_prop_get_endpoint,
 239                                   qcrypto_tls_creds_prop_set_endpoint,
 240                                   NULL);
 241    object_class_property_add_str(oc, "priority",
 242                                  qcrypto_tls_creds_prop_get_priority,
 243                                  qcrypto_tls_creds_prop_set_priority,
 244                                  NULL);
 245}
 246
 247
 248static void
 249qcrypto_tls_creds_init(Object *obj)
 250{
 251    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 252
 253    creds->verifyPeer = true;
 254}
 255
 256
 257static void
 258qcrypto_tls_creds_finalize(Object *obj)
 259{
 260    QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
 261
 262    g_free(creds->dir);
 263    g_free(creds->priority);
 264}
 265
 266
 267static const TypeInfo qcrypto_tls_creds_info = {
 268    .parent = TYPE_OBJECT,
 269    .name = TYPE_QCRYPTO_TLS_CREDS,
 270    .instance_size = sizeof(QCryptoTLSCreds),
 271    .instance_init = qcrypto_tls_creds_init,
 272    .instance_finalize = qcrypto_tls_creds_finalize,
 273    .class_init = qcrypto_tls_creds_class_init,
 274    .class_size = sizeof(QCryptoTLSCredsClass),
 275    .abstract = true,
 276};
 277
 278
 279static void
 280qcrypto_tls_creds_register_types(void)
 281{
 282    type_register_static(&qcrypto_tls_creds_info);
 283}
 284
 285
 286type_init(qcrypto_tls_creds_register_types);
 287