diff options
-rw-r--r-- | crypto/Makefile.objs | 1 | ||||
-rw-r--r-- | crypto/tlscreds.c | 251 | ||||
-rw-r--r-- | crypto/tlscredspriv.h | 42 | ||||
-rw-r--r-- | include/crypto/tlscreds.h | 68 | ||||
-rw-r--r-- | qapi-schema.json | 3 | ||||
-rw-r--r-- | qapi/crypto.json | 21 | ||||
-rw-r--r-- | tests/Makefile | 2 | ||||
-rw-r--r-- | trace-events | 4 |
8 files changed, 391 insertions, 1 deletions
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs index 2167fd2fdf..aef8dbb79d 100644 --- a/crypto/Makefile.objs +++ b/crypto/Makefile.objs @@ -3,6 +3,7 @@ crypto-obj-y += hash.o crypto-obj-y += aes.o crypto-obj-y += desrfb.o crypto-obj-y += cipher.o +crypto-obj-y += tlscreds.o # Let the userspace emulators avoid linking gnutls/etc crypto-aes-obj-y = aes.o diff --git a/crypto/tlscreds.c b/crypto/tlscreds.c new file mode 100644 index 0000000000..5ec982c6ee --- /dev/null +++ b/crypto/tlscreds.c @@ -0,0 +1,251 @@ +/* + * QEMU crypto TLS credential support + * + * 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/tlscredspriv.h" +#include "trace.h" + +#define DH_BITS 2048 + +#ifdef CONFIG_GNUTLS +int +qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds, + const char *filename, + gnutls_dh_params_t *dh_params, + Error **errp) +{ + int ret; + + trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>"); + + if (filename == NULL) { + ret = gnutls_dh_params_init(dh_params); + if (ret < 0) { + error_setg(errp, "Unable to initialize DH parameters: %s", + gnutls_strerror(ret)); + return -1; + } + ret = gnutls_dh_params_generate2(*dh_params, DH_BITS); + if (ret < 0) { + gnutls_dh_params_deinit(*dh_params); + *dh_params = NULL; + error_setg(errp, "Unable to generate DH parameters: %s", + gnutls_strerror(ret)); + return -1; + } + } else { + GError *gerr = NULL; + gchar *contents; + gsize len; + gnutls_datum_t data; + if (!g_file_get_contents(filename, + &contents, + &len, + &gerr)) { + + error_setg(errp, "%s", gerr->message); + g_error_free(gerr); + return -1; + } + data.data = (unsigned char *)contents; + data.size = len; + ret = gnutls_dh_params_init(dh_params); + if (ret < 0) { + g_free(contents); + error_setg(errp, "Unable to initialize DH parameters: %s", + gnutls_strerror(ret)); + return -1; + } + ret = gnutls_dh_params_import_pkcs3(*dh_params, + &data, + GNUTLS_X509_FMT_PEM); + g_free(contents); + if (ret < 0) { + gnutls_dh_params_deinit(*dh_params); + *dh_params = NULL; + error_setg(errp, "Unable to load DH parameters from %s: %s", + filename, gnutls_strerror(ret)); + return -1; + } + } + + return 0; +} + + +int +qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds, + const char *filename, + bool required, + char **cred, + Error **errp) +{ + struct stat sb; + int ret = -1; + + if (!creds->dir) { + if (required) { + error_setg(errp, "Missing 'dir' property value"); + return -1; + } else { + return 0; + } + } + + *cred = g_strdup_printf("%s/%s", creds->dir, filename); + + if (stat(*cred, &sb) < 0) { + if (errno == ENOENT && !required) { + ret = 0; + } else { + error_setg_errno(errp, errno, + "Unable to access credentials %s", + *cred); + } + g_free(*cred); + *cred = NULL; + goto cleanup; + } + + trace_qcrypto_tls_creds_get_path(creds, filename, + *cred ? *cred : "<none>"); + ret = 0; + cleanup: + return ret; +} + + +#endif /* ! CONFIG_GNUTLS */ + + +static void +qcrypto_tls_creds_prop_set_verify(Object *obj, + bool value, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + creds->verifyPeer = value; +} + + +static bool +qcrypto_tls_creds_prop_get_verify(Object *obj, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + return creds->verifyPeer; +} + + +static void +qcrypto_tls_creds_prop_set_dir(Object *obj, + const char *value, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + creds->dir = g_strdup(value); +} + + +static char * +qcrypto_tls_creds_prop_get_dir(Object *obj, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + return g_strdup(creds->dir); +} + + +static void +qcrypto_tls_creds_prop_set_endpoint(Object *obj, + int value, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + creds->endpoint = value; +} + + +static int +qcrypto_tls_creds_prop_get_endpoint(Object *obj, + Error **errp G_GNUC_UNUSED) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + return creds->endpoint; +} + + +static void +qcrypto_tls_creds_init(Object *obj) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + creds->verifyPeer = true; + + object_property_add_bool(obj, "verify-peer", + qcrypto_tls_creds_prop_get_verify, + qcrypto_tls_creds_prop_set_verify, + NULL); + object_property_add_str(obj, "dir", + qcrypto_tls_creds_prop_get_dir, + qcrypto_tls_creds_prop_set_dir, + NULL); + object_property_add_enum(obj, "endpoint", + "QCryptoTLSCredsEndpoint", + QCryptoTLSCredsEndpoint_lookup, + qcrypto_tls_creds_prop_get_endpoint, + qcrypto_tls_creds_prop_set_endpoint, + NULL); +} + + +static void +qcrypto_tls_creds_finalize(Object *obj) +{ + QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj); + + g_free(creds->dir); +} + + +static const TypeInfo qcrypto_tls_creds_info = { + .parent = TYPE_OBJECT, + .name = TYPE_QCRYPTO_TLS_CREDS, + .instance_size = sizeof(QCryptoTLSCreds), + .instance_init = qcrypto_tls_creds_init, + .instance_finalize = qcrypto_tls_creds_finalize, + .class_size = sizeof(QCryptoTLSCredsClass), + .abstract = true, +}; + + +static void +qcrypto_tls_creds_register_types(void) +{ + type_register_static(&qcrypto_tls_creds_info); +} + + +type_init(qcrypto_tls_creds_register_types); diff --git a/crypto/tlscredspriv.h b/crypto/tlscredspriv.h new file mode 100644 index 0000000000..9222be4a9e --- /dev/null +++ b/crypto/tlscredspriv.h @@ -0,0 +1,42 @@ +/* + * QEMU crypto TLS credential support private helpers + * + * 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/>. + * + */ + +#ifndef QCRYPTO_TLSCRED_PRIV_H__ +#define QCRYPTO_TLSCRED_PRIV_H__ + +#include "crypto/tlscreds.h" + +#ifdef CONFIG_GNUTLS + +int qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds, + const char *filename, + bool required, + char **cred, + Error **errp); + +int qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds, + const char *filename, + gnutls_dh_params_t *dh_params, + Error **errp); + +#endif + +#endif /* QCRYPTO_TLSCRED_PRIV_H__ */ + diff --git a/include/crypto/tlscreds.h b/include/crypto/tlscreds.h new file mode 100644 index 0000000000..21761b7ce1 --- /dev/null +++ b/include/crypto/tlscreds.h @@ -0,0 +1,68 @@ +/* + * QEMU crypto TLS credential support + * + * 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/>. + * + */ + +#ifndef QCRYPTO_TLSCRED_H__ +#define QCRYPTO_TLSCRED_H__ + +#include "qemu-common.h" +#include "qapi/error.h" +#include "qom/object.h" + +#ifdef CONFIG_GNUTLS +#include <gnutls/gnutls.h> +#endif + +#define TYPE_QCRYPTO_TLS_CREDS "tls-creds" +#define QCRYPTO_TLS_CREDS(obj) \ + OBJECT_CHECK(QCryptoTLSCreds, (obj), TYPE_QCRYPTO_TLS_CREDS) + +typedef struct QCryptoTLSCreds QCryptoTLSCreds; +typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass; + +#define QCRYPTO_TLS_CREDS_DH_PARAMS "dh-params.pem" + + +/** + * QCryptoTLSCreds: + * + * The QCryptoTLSCreds object is an abstract base for different + * types of TLS handshake credentials. Most commonly the + * QCryptoTLSCredsX509 subclass will be used to provide x509 + * certificate credentials. + */ + +struct QCryptoTLSCreds { + Object parent_obj; + char *dir; + QCryptoTLSCredsEndpoint endpoint; +#ifdef CONFIG_GNUTLS + gnutls_dh_params_t dh_params; +#endif + bool verifyPeer; +}; + + +struct QCryptoTLSCredsClass { + ObjectClass parent_class; +}; + + +#endif /* QCRYPTO_TLSCRED_H__ */ + diff --git a/qapi-schema.json b/qapi-schema.json index 4060b78386..2bada607f1 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5,6 +5,9 @@ # QAPI common definitions { 'include': 'qapi/common.json' } +# QAPI crypto definitions +{ 'include': 'qapi/crypto.json' } + # QAPI block definitions { 'include': 'qapi/block.json' } diff --git a/qapi/crypto.json b/qapi/crypto.json new file mode 100644 index 0000000000..b058b14d7b --- /dev/null +++ b/qapi/crypto.json @@ -0,0 +1,21 @@ +# -*- Mode: Python -*- +# +# QAPI crypto definitions + +## +# QCryptoTLSCredsEndpoint: +# +# The type of network endpoint that will be using the credentials. +# Most types of credential require different setup / structures +# depending on whether they will be used in a server versus a +# client. +# +# @client: the network endpoint is acting as the client +# +# @server: the network endpoint is acting as the server +# +# Since: 2.5 +## +{ 'enum': 'QCryptoTLSCredsEndpoint', + 'prefix': 'QCRYPTO_TLS_CREDS_ENDPOINT', + 'data': ['client', 'server']} diff --git a/tests/Makefile b/tests/Makefile index ddd5148988..827e732d7a 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -288,7 +288,7 @@ test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y) test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \ tests/test-qapi-event.o \ $(test-qom-obj-y) -test-crypto-obj-y = $(crypto-obj-y) $(test-util-obj-y) +test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y) test-block-obj-y = $(block-obj-y) $(test-crypto-obj-y) tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y) diff --git a/trace-events b/trace-events index 1927c764a9..e8103d1374 100644 --- a/trace-events +++ b/trace-events @@ -1666,3 +1666,7 @@ alsa_no_frames(int state) "No frames available and ALSA state is %d" # audio/ossaudio.c oss_version(int version) "OSS version = %#x" oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d" + +# crypto/tlscreds.c +qcrypto_tls_creds_load_dh(void *creds, const char *filename) "TLS creds load DH creds=%p filename=%s" +qcrypto_tls_creds_get_path(void *creds, const char *filename, const char *path) "TLS creds path creds=%p filename=%s path=%s" |