From nobody Sun May 5 23:33:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=yandex-team.ru ARC-Seal: i=1; a=rsa-sha256; t=1585407160; cv=none; d=zohomail.com; s=zohoarc; b=RezFZ0kMh9IL/F4S1tvWDdX0/jjpYqrnpDjD0WLyV+PFgqTm5LWDZ4yAKioa6au8Z6zq2CZW/xeYz3XyX/kkYrJZnzXvGUsjsV/uqPvJ30TvNE8+9aE1UfvmT8Rni5qhIzWbyndBQezxOaw0z0LUQ/YiNLC5Kage9nohkJ/Wodo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1585407160; h=Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:Sender:Subject:To; bh=4eVtLQG3em9wzX00O5mcBGQDiDZUIbsALFFrNXvVOaE=; b=ZiqUQQNrbmMia7w+PZd17/ZdSSPd+wxR7WtCjNeLe5Qpf6yQuJXD4vRtp8JnVm4Pk9nI30SwtmzJiLKtHG3Uzrx5nONiMDRSISddnarvORr0JNv5DvT4f+mB5jvGdykqfCHOikAK7UvFoj518ERkPcLQZySc2tZk6Vmm9Xxo9nI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1585407160968180.7029564163554; Sat, 28 Mar 2020 07:52:40 -0700 (PDT) Received: from localhost ([::1]:53742 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jICpD-0004LU-Ds for importer@patchew.org; Sat, 28 Mar 2020 10:52:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:45076) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jI9pI-00087L-HQ for qemu-devel@nongnu.org; Sat, 28 Mar 2020 07:40:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jI9pE-0005Fl-Jm for qemu-devel@nongnu.org; Sat, 28 Mar 2020 07:40:30 -0400 Received: from forwardcorp1j.mail.yandex.net ([2a02:6b8:0:1619::183]:47348) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1jI9pD-0005C3-T1 for qemu-devel@nongnu.org; Sat, 28 Mar 2020 07:40:28 -0400 Received: from mxbackcorp2j.mail.yandex.net (mxbackcorp2j.mail.yandex.net [IPv6:2a02:6b8:0:1619::119]) by forwardcorp1j.mail.yandex.net (Yandex) with ESMTP id 450152E09D9; Sat, 28 Mar 2020 14:40:22 +0300 (MSK) Received: from sas1-9998cec34266.qloud-c.yandex.net (sas1-9998cec34266.qloud-c.yandex.net [2a02:6b8:c14:3a0e:0:640:9998:cec3]) by mxbackcorp2j.mail.yandex.net (mxbackcorp/Yandex) with ESMTP id txwmjhNGTR-eM8iv00B; Sat, 28 Mar 2020 14:40:22 +0300 Received: from unknown (unknown [2a02:6b8:b080:8404::1:3]) by sas1-9998cec34266.qloud-c.yandex.net (smtpcorp/Yandex) with ESMTPSA id 6lMAd8fQ0l-eLWWloOM; Sat, 28 Mar 2020 14:40:21 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) Precedence: bulk DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex-team.ru; s=default; t=1585395622; bh=4eVtLQG3em9wzX00O5mcBGQDiDZUIbsALFFrNXvVOaE=; h=Message-Id:Date:Subject:To:From:Cc; b=ic0nQMeWWDucDA7H5XVq3ws5imhsbVerEngPFVKZMs2cZ3Kzbhfi3QXb6az8odYBG q9wvuBeHbVXwvZYMBEeaQR2Y7JZTznHe9kbJqU8xpAnPTI5LJLrCita+hyBzEMDdSJ 2keehLg03dwyB9SMfmei6Muw6W1F5K0S4WtF8j1c= Authentication-Results: mxbackcorp2j.mail.yandex.net; dkim=pass header.i=@yandex-team.ru From: Alexey Krasikov To: berrange@redhat.com, qemu-devel@nongnu.org Subject: [RFC PATCH] crypto/secret: support fetching secrets from Linux keyring Date: Sat, 28 Mar 2020 14:40:14 +0300 Message-Id: <20200328114014.6362-1-alex-krasikov@yandex-team.ru> X-Mailer: git-send-email 2.17.1 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a02:6b8:0:1619::183 X-Mailman-Approved-At: Sat, 28 Mar 2020 10:51:49 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: yc-core@yandex-team.ru Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @yandex-team.ru) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 rights to read it. Signed-off-by: Alexey Krasikov --- crypto/secret.c | 88 +++++++++++++++++++++++++++++++++++++++-- include/crypto/secret.h | 3 ++ 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/crypto/secret.c b/crypto/secret.c index 1cf0ad0ce8..2e8be6241c 100644 --- a/crypto/secret.c +++ b/crypto/secret.c @@ -19,6 +19,8 @@ */ =20 #include "qemu/osdep.h" +#include +#include #include "crypto/secret.h" #include "crypto/cipher.h" #include "qapi/error.h" @@ -28,6 +30,40 @@ #include "trace.h" =20 =20 +static inline +long keyctl_read(key_serial_t key, uint8_t *buffer, size_t buflen) +{ +#ifdef __NR_keyctl + return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen, 0); +#else + errno =3D ENOSYS; + return -1; +#endif +} + +static +long keyctl_read_alloc(key_serial_t key, uint8_t **buffer) +{ + uint8_t *loc_buf; + long retcode =3D keyctl_read(key, NULL, 0); + if (retcode < 0) { + return retcode; + } + loc_buf =3D g_malloc(retcode + 1); + retcode =3D keyctl_read(key, loc_buf, retcode + 1); + /* + * We don't have key operations locks between syscalls. + * For example, the key could have been removed or expired. + */ + if (retcode >=3D 0) { + loc_buf[retcode] =3D '\0'; + *buffer =3D loc_buf; + } else { + g_free(loc_buf); + } + return retcode; +} + static void qcrypto_secret_load_data(QCryptoSecret *secret, uint8_t **output, @@ -41,10 +77,28 @@ qcrypto_secret_load_data(QCryptoSecret *secret, *output =3D NULL; *outputlen =3D 0; =20 - if (secret->file) { + if (secret->syskey) { + uint8_t *buffer =3D NULL; + long retcode; + if (secret->data || secret->file) { + error_setg(errp, + "'syskey', 'file' and 'data' are mutually exclusive= "); + return; + } + retcode =3D keyctl_read_alloc(secret->syskey, &buffer); + if (retcode < 0) { + error_setg_errno(errp, errno, + "Unable to read serial key %08x", + secret->syskey); + return; + } else { + *outputlen =3D retcode; + *output =3D buffer; + } + } else if (secret->file) { if (secret->data) { error_setg(errp, - "'file' and 'data' are mutually exclusive"); + "'syskey', 'file' and 'data' are mutually exclusive= "); return; } if (!g_file_get_contents(secret->file, &data, &length, &gerr)) { @@ -60,7 +114,8 @@ qcrypto_secret_load_data(QCryptoSecret *secret, *outputlen =3D strlen(secret->data); *output =3D (uint8_t *)g_strdup(secret->data); } else { - error_setg(errp, "Either 'file' or 'data' must be provided"); + error_setg(errp, + "Either 'syskey' or 'file' or 'data' must be provided"); } } =20 @@ -298,6 +353,29 @@ qcrypto_secret_prop_get_file(Object *obj, } =20 =20 +static void +qcrypto_secret_prop_set_syskey(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + QCryptoSecret *secret =3D QCRYPTO_SECRET(obj); + int32_t value; + visit_type_int32(v, name, &value, errp); + secret->syskey =3D value; +} + + +static void +qcrypto_secret_prop_get_syskey(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + QCryptoSecret *secret =3D QCRYPTO_SECRET(obj); + int32_t value =3D secret->syskey; + visit_type_int32(v, name, &value, errp); +} + + static void qcrypto_secret_prop_set_iv(Object *obj, const char *value, @@ -384,6 +462,10 @@ qcrypto_secret_class_init(ObjectClass *oc, void *data) qcrypto_secret_prop_get_file, qcrypto_secret_prop_set_file, NULL); + object_class_property_add(oc, "syskey", "key_serial_t", + qcrypto_secret_prop_get_syskey, + qcrypto_secret_prop_set_syskey, + NULL, NULL, NULL); object_class_property_add_str(oc, "keyid", qcrypto_secret_prop_get_keyid, qcrypto_secret_prop_set_keyid, diff --git a/include/crypto/secret.h b/include/crypto/secret.h index 5e07e29bae..9d350e35ed 100644 --- a/include/crypto/secret.h +++ b/include/crypto/secret.h @@ -31,6 +31,8 @@ typedef struct QCryptoSecret QCryptoSecret; typedef struct QCryptoSecretClass QCryptoSecretClass; =20 +typedef int32_t key_serial_t; + /** * QCryptoSecret: * @@ -125,6 +127,7 @@ struct QCryptoSecret { QCryptoSecretFormat format; char *data; char *file; + key_serial_t syskey; char *keyid; char *iv; }; --=20 2.17.1