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