From: "Daniel P. Berrangé" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Alexey Krasikov" <alex-krasikov@yandex-team.ru>,
"Daniel P. Berrangé" <berrange@redhat.com>
Subject: [PULL 3/5] crypto/linux_keyring: add 'secret_keyring' secret object.
Date: Fri, 29 May 2020 11:35:53 +0100 [thread overview]
Message-ID: <20200529103555.2759928-4-berrange@redhat.com> (raw)
In-Reply-To: <20200529103555.2759928-1-berrange@redhat.com>
From: Alexey Krasikov <alex-krasikov@yandex-team.ru>
Add the ability for the secret object to obtain secret data from the
Linux in-kernel key managment and retention facility, as an extra option
to the existing ones: reading from a file or passing directly as a
string.
The secret is identified by the key serial number. The upper layers
need to instantiate the key and make sure the QEMU process has access
permissions to read it.
Signed-off-by: Alexey Krasikov <alex-krasikov@yandex-team.ru>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
configure | 38 ++++++++
crypto/Makefile.objs | 1 +
crypto/secret_keyring.c | 148 ++++++++++++++++++++++++++++++++
include/crypto/secret_keyring.h | 52 +++++++++++
4 files changed, 239 insertions(+)
create mode 100644 crypto/secret_keyring.c
create mode 100644 include/crypto/secret_keyring.h
diff --git a/configure b/configure
index 2ffe365e2c..d95ff4e0b3 100755
--- a/configure
+++ b/configure
@@ -510,6 +510,7 @@ default_devices="yes"
plugins="no"
fuzzing="no"
rng_none="no"
+secret_keyring="yes"
supported_cpu="no"
supported_os="no"
@@ -1606,6 +1607,10 @@ for opt do
;;
--disable-rng-none) rng_none=no
;;
+ --enable-keyring) secret_keyring="yes"
+ ;;
+ --disable-keyring) secret_keyring="no"
+ ;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -6272,6 +6277,34 @@ case "$slirp" in
;;
esac
+##########################################
+# check for usable __NR_keyctl syscall
+
+if test "$linux" = "yes" ; then
+
+ have_keyring=no
+ cat > $TMPC << EOF
+#include <errno.h>
+#include <asm/unistd.h>
+#include <linux/keyctl.h>
+#include <unistd.h>
+int main(void) {
+ return syscall(__NR_keyctl, KEYCTL_READ, 0, NULL, NULL, 0);
+}
+EOF
+ if compile_prog "" "" ; then
+ have_keyring=yes
+ fi
+fi
+if test "$secret_keyring" = "yes"
+then
+ if test "$have_keyring" != "yes"
+ then
+ error_exit "syscall __NR_keyctl requested, \
+but not implemented on your system"
+ fi
+fi
+
##########################################
# End of CC checks
@@ -6756,6 +6789,7 @@ echo "plugin support $plugins"
echo "fuzzing support $fuzzing"
echo "gdb $gdb_bin"
echo "rng-none $rng_none"
+echo "Linux keyring $secret_keyring"
if test "$supported_cpu" = "no"; then
echo
@@ -7638,6 +7672,10 @@ if test -n "$gdb_bin" ; then
echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak
fi
+if test "$secret_keyring" = "yes" ; then
+ echo "CONFIG_SECRET_KEYRING=y" >> $config_host_mak
+fi
+
if test "$tcg_interpreter" = "yes"; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
elif test "$ARCH" = "sparc64" ; then
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 110dec1b87..707c02ad37 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -20,6 +20,7 @@ crypto-obj-y += tlscredsx509.o
crypto-obj-y += tlssession.o
crypto-obj-y += secret_common.o
crypto-obj-y += secret.o
+crypto-obj-$(CONFIG_SECRET_KEYRING) += secret_keyring.o
crypto-obj-y += pbkdf.o
crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o
diff --git a/crypto/secret_keyring.c b/crypto/secret_keyring.c
new file mode 100644
index 0000000000..4f132d6370
--- /dev/null
+++ b/crypto/secret_keyring.c
@@ -0,0 +1,148 @@
+/*
+ * QEMU crypto secret support
+ *
+ * Copyright 2020 Yandex N.V.
+ *
+ * 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.1 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 "qemu/osdep.h"
+#include <asm/unistd.h>
+#include <linux/keyctl.h>
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "trace.h"
+#include "crypto/secret_keyring.h"
+
+
+static inline
+long keyctl_read(int32_t key, uint8_t *buffer, size_t buflen)
+{
+ return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen, 0);
+}
+
+
+static void
+qcrypto_secret_keyring_load_data(QCryptoSecretCommon *sec_common,
+ uint8_t **output,
+ size_t *outputlen,
+ Error **errp)
+{
+ QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(sec_common);
+ uint8_t *buffer = NULL;
+ long retcode;
+
+ *output = NULL;
+ *outputlen = 0;
+
+ if (!secret->serial) {
+ error_setg(errp, "'serial' parameter must be provided");
+ return;
+ }
+
+ retcode = keyctl_read(secret->serial, NULL, 0);
+ if (retcode <= 0) {
+ goto keyctl_error;
+ }
+
+ buffer = g_new0(uint8_t, retcode);
+
+ retcode = keyctl_read(secret->serial, buffer, retcode);
+ if (retcode < 0) {
+ g_free(buffer);
+ goto keyctl_error;
+ }
+
+ *outputlen = retcode;
+ *output = buffer;
+ return;
+
+keyctl_error:
+ error_setg_errno(errp, errno,
+ "Unable to read serial key %08x",
+ secret->serial);
+}
+
+
+static void
+qcrypto_secret_prop_set_key(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj);
+ int32_t value;
+ visit_type_int32(v, name, &value, errp);
+ if (!value) {
+ error_setg(errp, "'serial' should not be equal to 0");
+ }
+ secret->serial = value;
+}
+
+
+static void
+qcrypto_secret_prop_get_key(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ QCryptoSecretKeyring *secret = QCRYPTO_SECRET_KEYRING(obj);
+ int32_t value = secret->serial;
+ visit_type_int32(v, name, &value, errp);
+}
+
+
+static void
+qcrypto_secret_keyring_complete(UserCreatable *uc, Error **errp)
+{
+ object_property_set_bool(OBJECT(uc), true, "loaded", errp);
+}
+
+
+static void
+qcrypto_secret_keyring_class_init(ObjectClass *oc, void *data)
+{
+ QCryptoSecretCommonClass *sic = QCRYPTO_SECRET_COMMON_CLASS(oc);
+ sic->load_data = qcrypto_secret_keyring_load_data;
+
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ ucc->complete = qcrypto_secret_keyring_complete;
+
+ object_class_property_add(oc, "serial", "int32_t",
+ qcrypto_secret_prop_get_key,
+ qcrypto_secret_prop_set_key,
+ NULL, NULL);
+}
+
+
+static const TypeInfo qcrypto_secret_info = {
+ .parent = TYPE_QCRYPTO_SECRET_COMMON,
+ .name = TYPE_QCRYPTO_SECRET_KEYRING,
+ .instance_size = sizeof(QCryptoSecretKeyring),
+ .class_size = sizeof(QCryptoSecretKeyringClass),
+ .class_init = qcrypto_secret_keyring_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+
+static void
+qcrypto_secret_register_types(void)
+{
+ type_register_static(&qcrypto_secret_info);
+}
+
+
+type_init(qcrypto_secret_register_types);
diff --git a/include/crypto/secret_keyring.h b/include/crypto/secret_keyring.h
new file mode 100644
index 0000000000..9f371ad251
--- /dev/null
+++ b/include/crypto/secret_keyring.h
@@ -0,0 +1,52 @@
+/*
+ * QEMU crypto secret support
+ *
+ * Copyright 2020 Yandex N.V.
+ *
+ * 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.1 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_SECRET_KEYRING_H
+#define QCRYPTO_SECRET_KEYRING_H
+
+#include "qapi/qapi-types-crypto.h"
+#include "qom/object.h"
+#include "crypto/secret_common.h"
+
+#define TYPE_QCRYPTO_SECRET_KEYRING "secret_keyring"
+#define QCRYPTO_SECRET_KEYRING(obj) \
+ OBJECT_CHECK(QCryptoSecretKeyring, (obj), \
+ TYPE_QCRYPTO_SECRET_KEYRING)
+#define QCRYPTO_SECRET_KEYRING_CLASS(class) \
+ OBJECT_CLASS_CHECK(QCryptoSecretKeyringClass, \
+ (class), TYPE_QCRYPTO_SECRET_KEYRING)
+#define QCRYPTO_SECRET_KEYRING_GET_CLASS(class) \
+ OBJECT_GET_CLASS(QCryptoSecretKeyringClass, \
+ (class), TYPE_QCRYPTO_SECRET_KEYRING)
+
+typedef struct QCryptoSecretKeyring QCryptoSecretKeyring;
+typedef struct QCryptoSecretKeyringClass QCryptoSecretKeyringClass;
+
+typedef struct QCryptoSecretKeyring {
+ QCryptoSecretCommon parent;
+ int32_t serial;
+} QCryptoSecretKeyring;
+
+
+typedef struct QCryptoSecretKeyringClass {
+ QCryptoSecretCommonClass parent;
+} QCryptoSecretKeyringClass;
+
+#endif /* QCRYPTO_SECRET_KEYRING_H */
--
2.26.2
next prev parent reply other threads:[~2020-05-29 10:38 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-29 10:35 [PULL 0/5] Qcrypto next patches Daniel P. Berrangé
2020-05-29 10:35 ` [PULL 1/5] crypto: add "none" random provider Daniel P. Berrangé
2020-05-29 10:35 ` [PULL 2/5] crypto/secret: move main logic from 'secret' to 'secret_common' Daniel P. Berrangé
2020-05-29 10:35 ` Daniel P. Berrangé [this message]
2020-06-05 11:06 ` [PULL 3/5] crypto/linux_keyring: add 'secret_keyring' secret object Daniel P. Berrangé
2020-05-29 10:35 ` [PULL 4/5] test-crypto-secret: add 'secret_keyring' object tests Daniel P. Berrangé
2020-05-29 10:35 ` [PULL 5/5] crypto: Remove use of GCRYPT_VERSION macro Daniel P. Berrangé
2020-05-29 17:04 ` [PULL 0/5] Qcrypto next patches no-reply
2020-05-29 17:08 ` Daniel P. Berrangé
-- strict thread matches above, loose matches on Subject: below --
2020-06-15 10:36 [PULL v2 " Daniel P. Berrangé
2020-06-15 10:36 ` [PULL 3/5] crypto/linux_keyring: add 'secret_keyring' secret object Daniel P. Berrangé
2020-06-16 16:49 ` David Edmondson
2020-06-16 16:51 ` Daniel P. Berrangé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200529103555.2759928-4-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=alex-krasikov@yandex-team.ru \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.