linux-efi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Peter Gonda <pgonda@google.com>
To: Brijesh Singh <brijesh.singh@amd.com>
Cc: x86@kernel.org, LKML <linux-kernel@vger.kernel.org>,
	kvm list <kvm@vger.kernel.org>,
	linux-efi@vger.kernel.org, platform-driver-x86@vger.kernel.org,
	linux-coco@lists.linux.dev, linux-mm@kvack.org,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Joerg Roedel <jroedel@suse.de>,
	Tom Lendacky <Thomas.Lendacky@amd.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Ard Biesheuvel <ardb@kernel.org>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Sean Christopherson <seanjc@google.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Jim Mattson <jmattson@google.com>,
	Andy Lutomirski <luto@kernel.org>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Sergio Lopez <slp@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>,
	David Rientjes <rientjes@google.com>,
	Dov Murik <dovmurik@linux.ibm.com>,
	Tobin Feldman-Fitzthum <tobin@ibm.com>,
	Borislav Petkov <bp@alien8.de>,
	Michael Roth <michael.roth@amd.com>,
	Vlastimil Babka <vbabka@suse.cz>,
	"Kirill A . Shutemov" <kirill@shutemov.name>,
	Andi Kleen <ak@linux.intel.com>,
	"Dr . David Alan Gilbert" <dgilbert@redhat.com>,
	tony.luck@intel.com, Marc Orr <marcorr@google.com>,
	sathyanarayanan.kuppuswamy@linux.intel.com
Subject: Re: [PATCH v6 40/42] virt: Add SEV-SNP guest driver
Date: Wed, 27 Oct 2021 14:10:20 -0600	[thread overview]
Message-ID: <CAMkAt6pCSNZiB7zVXp=70fF-qORZT0D5KCSY=GrJU0iiLZN_Mw@mail.gmail.com> (raw)
In-Reply-To: <bf55b53c-cc3d-f2c3-cf21-df6fb4882e13@amd.com>

On Wed, Oct 27, 2021 at 10:08 AM Brijesh Singh <brijesh.singh@amd.com> wrote:
>
> Hi Peter,
>
> Somehow this email was filtered out as spam and never reached to my
> inbox. Sorry for the delay in the response.
>
> On 10/20/21 4:33 PM, Peter Gonda wrote:
> > On Fri, Oct 8, 2021 at 12:06 PM Brijesh Singh <brijesh.singh@amd.com> wrote:
> >>
> >> SEV-SNP specification provides the guest a mechanisum to communicate with
> >> the PSP without risk from a malicious hypervisor who wishes to read, alter,
> >> drop or replay the messages sent. The driver uses snp_issue_guest_request()
> >> to issue GHCB SNP_GUEST_REQUEST or SNP_EXT_GUEST_REQUEST NAE events to
> >> submit the request to PSP.
> >>
> >> The PSP requires that all communication should be encrypted using key
> >> specified through the platform_data.
> >>
> >> The userspace can use SNP_GET_REPORT ioctl() to query the guest
> >> attestation report.
> >>
> >> See SEV-SNP spec section Guest Messages for more details.
> >>
> >> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> >> ---
> >>   Documentation/virt/coco/sevguest.rst  |  77 ++++
> >>   drivers/virt/Kconfig                  |   3 +
> >>   drivers/virt/Makefile                 |   1 +
> >>   drivers/virt/coco/sevguest/Kconfig    |   9 +
> >>   drivers/virt/coco/sevguest/Makefile   |   2 +
> >>   drivers/virt/coco/sevguest/sevguest.c | 561 ++++++++++++++++++++++++++
> >>   drivers/virt/coco/sevguest/sevguest.h |  98 +++++
> >>   include/uapi/linux/sev-guest.h        |  44 ++
> >>   8 files changed, 795 insertions(+)
> >>   create mode 100644 Documentation/virt/coco/sevguest.rst
> >>   create mode 100644 drivers/virt/coco/sevguest/Kconfig
> >>   create mode 100644 drivers/virt/coco/sevguest/Makefile
> >>   create mode 100644 drivers/virt/coco/sevguest/sevguest.c
> >>   create mode 100644 drivers/virt/coco/sevguest/sevguest.h
> >>   create mode 100644 include/uapi/linux/sev-guest.h
> >>
> >> diff --git a/Documentation/virt/coco/sevguest.rst b/Documentation/virt/coco/sevguest.rst
> >> new file mode 100644
> >> index 000000000000..002c90946b8a
> >> --- /dev/null
> >> +++ b/Documentation/virt/coco/sevguest.rst
> >> @@ -0,0 +1,77 @@
> >> +.. SPDX-License-Identifier: GPL-2.0
> >> +
> >> +===================================================================
> >> +The Definitive SEV Guest API Documentation
> >> +===================================================================
> >> +
> >> +1. General description
> >> +======================
> >> +
> >> +The SEV API is a set of ioctls that are used by the guest or hypervisor
> >> +to get or set certain aspect of the SEV virtual machine. The ioctls belong
> >> +to the following classes:
> >> +
> >> + - Hypervisor ioctls: These query and set global attributes which affect the
> >> +   whole SEV firmware.  These ioctl are used by platform provision tools.
> >> +
> >> + - Guest ioctls: These query and set attributes of the SEV virtual machine.
> >> +
> >> +2. API description
> >> +==================
> >> +
> >> +This section describes ioctls that can be used to query or set SEV guests.
> >> +For each ioctl, the following information is provided along with a
> >> +description:
> >> +
> >> +  Technology:
> >> +      which SEV techology provides this ioctl. sev, sev-es, sev-snp or all.
> >> +
> >> +  Type:
> >> +      hypervisor or guest. The ioctl can be used inside the guest or the
> >> +      hypervisor.
> >> +
> >> +  Parameters:
> >> +      what parameters are accepted by the ioctl.
> >> +
> >> +  Returns:
> >> +      the return value.  General error numbers (ENOMEM, EINVAL)
> >> +      are not detailed, but errors with specific meanings are.
> >> +
> >> +The guest ioctl should be issued on a file descriptor of the /dev/sev-guest device.
> >> +The ioctl accepts struct snp_user_guest_request. The input and output structure is
> >> +specified through the req_data and resp_data field respectively. If the ioctl fails
> >> +to execute due to a firmware error, then fw_err code will be set.
> >> +
> >> +::
> >> +        struct snp_guest_request_ioctl {
> >> +                /* Request and response structure address */
> >> +                __u64 req_data;
> >> +                __u64 resp_data;
> >> +
> >> +                /* firmware error code on failure (see psp-sev.h) */
> >> +                __u64 fw_err;
> >> +        };
> >> +
> >> +2.1 SNP_GET_REPORT
> >> +------------------
> >> +
> >> +:Technology: sev-snp
> >> +:Type: guest ioctl
> >> +:Parameters (in): struct snp_report_req
> >> +:Returns (out): struct snp_report_resp on success, -negative on error
> >> +
> >> +The SNP_GET_REPORT ioctl can be used to query the attestation report from the
> >> +SEV-SNP firmware. The ioctl uses the SNP_GUEST_REQUEST (MSG_REPORT_REQ) command
> >> +provided by the SEV-SNP firmware to query the attestation report.
> >> +
> >> +On success, the snp_report_resp.data will contains the report. The report
> >> +will contain the format described in the SEV-SNP specification. See the SEV-SNP
> >> +specification for further details.
> >> +
> >> +
> >> +Reference
> >> +---------
> >> +
> >> +SEV-SNP and GHCB specification: developer.amd.com/sev
> >> +
> >> +The driver is based on SEV-SNP firmware spec 0.9 and GHCB spec version 2.0.
> >> diff --git a/drivers/virt/Kconfig b/drivers/virt/Kconfig
> >> index 8061e8ef449f..e457e47610d3 100644
> >> --- a/drivers/virt/Kconfig
> >> +++ b/drivers/virt/Kconfig
> >> @@ -36,4 +36,7 @@ source "drivers/virt/vboxguest/Kconfig"
> >>   source "drivers/virt/nitro_enclaves/Kconfig"
> >>
> >>   source "drivers/virt/acrn/Kconfig"
> >> +
> >> +source "drivers/virt/coco/sevguest/Kconfig"
> >> +
> >>   endif
> >> diff --git a/drivers/virt/Makefile b/drivers/virt/Makefile
> >> index 3e272ea60cd9..9c704a6fdcda 100644
> >> --- a/drivers/virt/Makefile
> >> +++ b/drivers/virt/Makefile
> >> @@ -8,3 +8,4 @@ obj-y                           += vboxguest/
> >>
> >>   obj-$(CONFIG_NITRO_ENCLAVES)   += nitro_enclaves/
> >>   obj-$(CONFIG_ACRN_HSM)         += acrn/
> >> +obj-$(CONFIG_SEV_GUEST)                += coco/sevguest/
> >> diff --git a/drivers/virt/coco/sevguest/Kconfig b/drivers/virt/coco/sevguest/Kconfig
> >> new file mode 100644
> >> index 000000000000..96190919cca8
> >> --- /dev/null
> >> +++ b/drivers/virt/coco/sevguest/Kconfig
> >> @@ -0,0 +1,9 @@
> >> +config SEV_GUEST
> >> +       tristate "AMD SEV Guest driver"
> >> +       default y
> >> +       depends on AMD_MEM_ENCRYPT && CRYPTO_AEAD2
> >> +       help
> >> +         The driver can be used by the SEV-SNP guest to communicate with the PSP to
> >> +         request the attestation report and more.
> >> +
> >> +         If you choose 'M' here, this module will be called sevguest.
> >> diff --git a/drivers/virt/coco/sevguest/Makefile b/drivers/virt/coco/sevguest/Makefile
> >> new file mode 100644
> >> index 000000000000..b1ffb2b4177b
> >> --- /dev/null
> >> +++ b/drivers/virt/coco/sevguest/Makefile
> >> @@ -0,0 +1,2 @@
> >> +# SPDX-License-Identifier: GPL-2.0-only
> >> +obj-$(CONFIG_SEV_GUEST) += sevguest.o
> >> diff --git a/drivers/virt/coco/sevguest/sevguest.c b/drivers/virt/coco/sevguest/sevguest.c
> >> new file mode 100644
> >> index 000000000000..2d313fb2ffae
> >> --- /dev/null
> >> +++ b/drivers/virt/coco/sevguest/sevguest.c
> >> @@ -0,0 +1,561 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * AMD Secure Encrypted Virtualization Nested Paging (SEV-SNP) guest request interface
> >> + *
> >> + * Copyright (C) 2021 Advanced Micro Devices, Inc.
> >> + *
> >> + * Author: Brijesh Singh <brijesh.singh@amd.com>
> >> + */
> >> +
> >> +#include <linux/module.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/types.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/io.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/miscdevice.h>
> >> +#include <linux/set_memory.h>
> >> +#include <linux/fs.h>
> >> +#include <crypto/aead.h>
> >> +#include <linux/scatterlist.h>
> >> +#include <linux/psp-sev.h>
> >> +#include <uapi/linux/sev-guest.h>
> >> +#include <uapi/linux/psp-sev.h>
> >> +
> >> +#include <asm/svm.h>
> >> +#include <asm/sev.h>
> >> +
> >> +#include "sevguest.h"
> >> +
> >> +#define DEVICE_NAME    "sev-guest"
> >> +#define AAD_LEN                48
> >> +#define MSG_HDR_VER    1
> >> +
> >> +struct snp_guest_crypto {
> >> +       struct crypto_aead *tfm;
> >> +       u8 *iv, *authtag;
> >> +       int iv_len, a_len;
> >> +};
> >> +
> >> +struct snp_guest_dev {
> >> +       struct device *dev;
> >> +       struct miscdevice misc;
> >> +
> >> +       struct snp_guest_crypto *crypto;
> >> +       struct snp_guest_msg *request, *response;
> >> +       struct snp_secrets_page_layout *layout;
> >> +       struct snp_req_data input;
> >> +       u32 *os_area_msg_seqno;
> >> +};
> >> +
> >> +static u32 vmpck_id;
> >> +module_param(vmpck_id, uint, 0444);
> >> +MODULE_PARM_DESC(vmpck_id, "The VMPCK ID to use when communicating with the PSP.");
> >> +
> >> +static DEFINE_MUTEX(snp_cmd_mutex);
> >> +
> >> +static inline u64 __snp_get_msg_seqno(struct snp_guest_dev *snp_dev)
> >> +{
> >> +       u64 count;
> >> +
> >> +       /* Read the current message sequence counter from secrets pages */
> >> +       count = *snp_dev->os_area_msg_seqno;
> >> +
> >> +       return count + 1;
> >> +}
> >> +
> >> +/* Return a non-zero on success */
> >> +static u64 snp_get_msg_seqno(struct snp_guest_dev *snp_dev)
> >> +{
> >> +       u64 count = __snp_get_msg_seqno(snp_dev);
> >> +
> >> +       /*
> >> +        * The message sequence counter for the SNP guest request is a  64-bit
> >> +        * value but the version 2 of GHCB specification defines a 32-bit storage
> >> +        * for the it. If the counter exceeds the 32-bit value then return zero.
> >> +        * The caller should check the return value, but if the caller happen to
> >> +        * not check the value and use it, then the firmware treats zero as an
> >> +        * invalid number and will fail the  message request.
> >> +        */
> >> +       if (count >= UINT_MAX) {
> >> +               pr_err_ratelimited("SNP guest request message sequence counter overflow\n");
> >> +               return 0;
> >> +       }
> >> +
> >> +       return count;
> >> +}
> >> +
> >> +static void snp_inc_msg_seqno(struct snp_guest_dev *snp_dev)
> >> +{
> >> +       /*
> >> +        * The counter is also incremented by the PSP, so increment it by 2
> >> +        * and save in secrets page.
> >> +        */
> >> +       *snp_dev->os_area_msg_seqno += 2;
> >> +}
> >> +
> >> +static inline struct snp_guest_dev *to_snp_dev(struct file *file)
> >> +{
> >> +       struct miscdevice *dev = file->private_data;
> >> +
> >> +       return container_of(dev, struct snp_guest_dev, misc);
> >> +}
> >> +
> >> +static struct snp_guest_crypto *init_crypto(struct snp_guest_dev *snp_dev, u8 *key, size_t keylen)
> >> +{
> >> +       struct snp_guest_crypto *crypto;
> >> +
> >> +       crypto = kzalloc(sizeof(*crypto), GFP_KERNEL_ACCOUNT);
> >> +       if (!crypto)
> >> +               return NULL;
> >> +
> >> +       crypto->tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
> >> +       if (IS_ERR(crypto->tfm))
> >> +               goto e_free;
> >> +
> >> +       if (crypto_aead_setkey(crypto->tfm, key, keylen))
> >> +               goto e_free_crypto;
> >> +
> >> +       crypto->iv_len = crypto_aead_ivsize(crypto->tfm);
> >> +       if (crypto->iv_len < 12) {
> >> +               dev_err(snp_dev->dev, "IV length is less than 12.\n");
> >> +               goto e_free_crypto;
> >> +       }
> >> +
> >> +       crypto->iv = kmalloc(crypto->iv_len, GFP_KERNEL_ACCOUNT);
> >> +       if (!crypto->iv)
> >> +               goto e_free_crypto;
> >> +
> >> +       if (crypto_aead_authsize(crypto->tfm) > MAX_AUTHTAG_LEN) {
> >> +               if (crypto_aead_setauthsize(crypto->tfm, MAX_AUTHTAG_LEN)) {
> >> +                       dev_err(snp_dev->dev, "failed to set authsize to %d\n", MAX_AUTHTAG_LEN);
> >> +                       goto e_free_crypto;
> >> +               }
> >> +       }
> >> +
> >> +       crypto->a_len = crypto_aead_authsize(crypto->tfm);
> >> +       crypto->authtag = kmalloc(crypto->a_len, GFP_KERNEL_ACCOUNT);
> >> +       if (!crypto->authtag)
> >> +               goto e_free_crypto;
> >> +
> >> +       return crypto;
> >> +
> >> +e_free_crypto:
> >> +       crypto_free_aead(crypto->tfm);
> >> +e_free:
> >> +       kfree(crypto->iv);
> >> +       kfree(crypto->authtag);
> >> +       kfree(crypto);
> >> +
> >> +       return NULL;
> >> +}
> >> +
> >> +static void deinit_crypto(struct snp_guest_crypto *crypto)
> >> +{
> >> +       crypto_free_aead(crypto->tfm);
> >> +       kfree(crypto->iv);
> >> +       kfree(crypto->authtag);
> >> +       kfree(crypto);
> >> +}
> >> +
> >> +static int enc_dec_message(struct snp_guest_crypto *crypto, struct snp_guest_msg *msg,
> >> +                          u8 *src_buf, u8 *dst_buf, size_t len, bool enc)
> >> +{
> >> +       struct snp_guest_msg_hdr *hdr = &msg->hdr;
> >> +       struct scatterlist src[3], dst[3];
> >> +       DECLARE_CRYPTO_WAIT(wait);
> >> +       struct aead_request *req;
> >> +       int ret;
> >> +
> >> +       req = aead_request_alloc(crypto->tfm, GFP_KERNEL);
> >> +       if (!req)
> >> +               return -ENOMEM;
> >> +
> >> +       /*
> >> +        * AEAD memory operations:
> >> +        * +------ AAD -------+------- DATA -----+---- AUTHTAG----+
> >> +        * |  msg header      |  plaintext       |  hdr->authtag  |
> >> +        * | bytes 30h - 5Fh  |    or            |                |
> >> +        * |                  |   cipher         |                |
> >> +        * +------------------+------------------+----------------+
> >> +        */
> >> +       sg_init_table(src, 3);
> >> +       sg_set_buf(&src[0], &hdr->algo, AAD_LEN);
> >> +       sg_set_buf(&src[1], src_buf, hdr->msg_sz);
> >> +       sg_set_buf(&src[2], hdr->authtag, crypto->a_len);
> >> +
> >> +       sg_init_table(dst, 3);
> >> +       sg_set_buf(&dst[0], &hdr->algo, AAD_LEN);
> >> +       sg_set_buf(&dst[1], dst_buf, hdr->msg_sz);
> >> +       sg_set_buf(&dst[2], hdr->authtag, crypto->a_len);
> >> +
> >> +       aead_request_set_ad(req, AAD_LEN);
> >> +       aead_request_set_tfm(req, crypto->tfm);
> >> +       aead_request_set_callback(req, 0, crypto_req_done, &wait);
> >> +
> >> +       aead_request_set_crypt(req, src, dst, len, crypto->iv);
> >> +       ret = crypto_wait_req(enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req), &wait);
> >> +
> >> +       aead_request_free(req);
> >> +       return ret;
> >> +}
> >> +
> >> +static int __enc_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg,
> >> +                        void *plaintext, size_t len)
> >> +{
> >> +       struct snp_guest_crypto *crypto = snp_dev->crypto;
> >> +       struct snp_guest_msg_hdr *hdr = &msg->hdr;
> >> +
> >> +       memset(crypto->iv, 0, crypto->iv_len);
> >> +       memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno));
> >> +
> >> +       return enc_dec_message(crypto, msg, plaintext, msg->payload, len, true);
> >> +}
> >> +
> >> +static int dec_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg,
> >> +                      void *plaintext, size_t len)
> >> +{
> >> +       struct snp_guest_crypto *crypto = snp_dev->crypto;
> >> +       struct snp_guest_msg_hdr *hdr = &msg->hdr;
> >> +
> >> +       /* Build IV with response buffer sequence number */
> >> +       memset(crypto->iv, 0, crypto->iv_len);
> >> +       memcpy(crypto->iv, &hdr->msg_seqno, sizeof(hdr->msg_seqno));
> >> +
> >> +       return enc_dec_message(crypto, msg, msg->payload, plaintext, len, false);
> >> +}
> >> +
> >> +static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz)
> >> +{
> >> +       struct snp_guest_crypto *crypto = snp_dev->crypto;
> >> +       struct snp_guest_msg *resp = snp_dev->response;
> >> +       struct snp_guest_msg *req = snp_dev->request;
> >> +       struct snp_guest_msg_hdr *req_hdr = &req->hdr;
> >> +       struct snp_guest_msg_hdr *resp_hdr = &resp->hdr;
> >> +
> >> +       dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n",
> >> +               resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz);
> >> +
> >> +       /* Verify that the sequence counter is incremented by 1 */
> >> +       if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1)))
> >> +               return -EBADMSG;
> >> +
> >> +       /* Verify response message type and version number. */
> >> +       if (resp_hdr->msg_type != (req_hdr->msg_type + 1) ||
> >> +           resp_hdr->msg_version != req_hdr->msg_version)
> >> +               return -EBADMSG;
> >> +
> >> +       /*
> >> +        * If the message size is greater than our buffer length then return
> >> +        * an error.
> >> +        */
> >> +       if (unlikely((resp_hdr->msg_sz + crypto->a_len) > sz))
> >> +               return -EBADMSG;
> >> +
> >> +       return dec_payload(snp_dev, resp, payload, resp_hdr->msg_sz + crypto->a_len);
> >> +}
> >> +
> >> +static bool enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type,
> >> +                       void *payload, size_t sz)
> >> +{
> >> +       struct snp_guest_msg *req = snp_dev->request;
> >> +       struct snp_guest_msg_hdr *hdr = &req->hdr;
> >> +
> >> +       memset(req, 0, sizeof(*req));
> >> +
> >> +       hdr->algo = SNP_AEAD_AES_256_GCM;
> >> +       hdr->hdr_version = MSG_HDR_VER;
> >> +       hdr->hdr_sz = sizeof(*hdr);
> >> +       hdr->msg_type = type;
> >> +       hdr->msg_version = version;
> >> +       hdr->msg_seqno = seqno;
> >> +       hdr->msg_vmpck = vmpck_id;
> >> +       hdr->msg_sz = sz;
> >> +
> >> +       /* Verify the sequence number is non-zero */
> >> +       if (!hdr->msg_seqno)
> >> +               return -ENOSR;
> >> +
> >> +       dev_dbg(snp_dev->dev, "request [seqno %lld type %d version %d sz %d]\n",
> >> +               hdr->msg_seqno, hdr->msg_type, hdr->msg_version, hdr->msg_sz);
> >> +
> >> +       return __enc_payload(snp_dev, req, payload, sz);
> >> +}
> >> +
> >> +static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,
> >> +                               u8 type, void *req_buf, size_t req_sz, void *resp_buf,
> >> +                               u32 resp_sz, __u64 *fw_err)
> >> +{
> >> +       unsigned long err;
> >> +       u64 seqno;
> >> +       int rc;
> >> +
> >> +       /* Get message sequence and verify that its a non-zero */
> >> +       seqno = snp_get_msg_seqno(snp_dev);
> >> +       if (!seqno)
> >> +               return -EIO;
> >> +
> >> +       memset(snp_dev->response, 0, sizeof(*snp_dev->response));
> >> +
> >> +       /* Encrypt the userspace provided payload */
> >> +       rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       /* Call firmware to process the request */
> >> +       rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
> >> +       if (fw_err)
> >> +               *fw_err = err;
> >> +
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz);
> >> +       if (rc)
> >> +               return rc;
> >> +
> >> +       /* Increment to new message sequence after the command is successful. */
> >> +       snp_inc_msg_seqno(snp_dev);
> >
> > Thanks for updating this sequence number logic. But I still have some
> > concerns. In verify_and_dec_payload() we check the encryption header
> > but all these fields are accessible to the hypervisor, meaning it can
> > change the header and cause this sequence number to not get
> > incremented. We then will reuse the sequence number for the next
> > command, which isn't great for AES GCM. It seems very hard to tell if
> > the FW actually got our request and created a response there by
> > incrementing the sequence number by 2, or if the hypervisor is acting
> > in bad faith. It seems like to be safe we need to completely stop
> > using this vmpck if we cannot confirm the PSP has gotten our request
> > and created a response. Thoughts?
> >
>
> Very good point, I think we can detect this condition by rearranging the
> checks. The verify_and_dec_payload() is called only after the command is
> succesful and does the following checks
>
> 1) Verifies the header
> 2) Decrypts the payload
> 3) Later we increment the sequence
>
> If we arrange to the below order then we can avoid this condition.
> 1) Decrypt the payload
> 2) Increment the sequence number
> 3) Verify the header
>
> The descryption will succeed only if PSP constructed the payload.
>
> Does this make sense ?

Either ordering seems fine to me. I don't think it changes much though
since the header (bytes 30-50 according to the spec) are included in
the authenticated data of the encryption. So any hypervisor modictions
will lead to a decryption failure right?

Either case if we do fail the decryption, what are your thoughts on
not allowing further use of that VMPCK?

>
> thanks

  reply	other threads:[~2021-10-27 20:12 UTC|newest]

Thread overview: 96+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-08 18:04 [PATCH v6 00/42] Add AMD Secure Nested Paging (SEV-SNP) Guest Support Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 01/42] x86/mm: Extend cc_attr to include AMD SEV-SNP Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 02/42] x86/sev: Shorten GHCB terminate macro names Brijesh Singh
2021-10-11 13:15   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 03/42] x86/sev: Get rid of excessive use of defines Brijesh Singh
2021-10-11  8:48   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 04/42] x86/head64: Carve out the guest encryption postprocessing into a helper Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 05/42] x86/sev: Define the Linux specific guest termination reasons Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 06/42] x86/sev: Save the negotiated GHCB version Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 07/42] x86/sev: Add support for hypervisor feature VMGEXIT Brijesh Singh
2021-10-13 14:02   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 08/42] x86/sev-es: initialize sev_status/features within #VC handler Brijesh Singh
2021-10-18 14:29   ` Borislav Petkov
2021-10-18 18:40     ` Michael Roth
2021-10-18 19:18       ` Borislav Petkov
2021-10-20 16:10         ` Michael Roth
2021-10-20 18:01           ` Borislav Petkov
2021-10-21  0:35             ` Michael Roth
2021-10-21 14:28               ` Borislav Petkov
2021-10-20 18:08           ` Borislav Petkov
2021-10-21  2:05             ` Michael Roth
2021-10-21 14:39               ` Borislav Petkov
2021-10-21 23:00                 ` Michael Roth
2021-10-21 14:48           ` Borislav Petkov
2021-10-21 15:56             ` Dr. David Alan Gilbert
2021-10-21 16:55               ` Borislav Petkov
2021-10-21 17:12                 ` Dr. David Alan Gilbert
2021-10-21 17:37                   ` Borislav Petkov
2021-10-21 17:47                     ` Dr. David Alan Gilbert
2021-10-21 18:46                       ` Borislav Petkov
2021-10-21 21:34             ` Michael Roth
2021-10-21 14:51           ` Borislav Petkov
2021-10-21 20:41             ` Michael Roth
2021-10-25 11:04               ` Borislav Petkov
2021-10-25 16:35                 ` Michael Roth
2021-10-27 11:17                   ` Borislav Petkov
2021-10-27 15:13                     ` Michael Roth
2021-10-08 18:04 ` [PATCH v6 09/42] x86/sev: Check SEV-SNP features support Brijesh Singh
2021-10-19 14:47   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 10/42] x86/sev: Add a helper for the PVALIDATE instruction Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 11/42] x86/sev: Check the vmpl level Brijesh Singh
2021-10-28 15:07   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 12/42] x86/compressed: Add helper for validating pages in the decompression stage Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 13/42] x86/compressed: Register GHCB memory when SEV-SNP is active Brijesh Singh
2021-11-02 16:33   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 14/42] x86/sev: " Brijesh Singh
2021-11-02 16:53   ` Borislav Petkov
2021-11-02 18:24     ` Brijesh Singh
2021-11-02 18:44       ` Borislav Petkov
2021-11-03 20:10         ` Brijesh Singh
2021-11-04 13:58           ` Borislav Petkov
2021-11-04 15:26             ` Brijesh Singh
2021-11-04 16:03               ` Boris Petkov
2021-10-08 18:04 ` [PATCH v6 15/42] x86/sev: Remove do_early_exception() forward declarations Brijesh Singh
2021-11-02 16:54   ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 16/42] x86/sev: Add helper for validating pages in early enc attribute changes Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 17/42] x86/kernel: Make the bss.decrypted section shared in RMP table Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 18/42] x86/kernel: Validate rom memory before accessing when SEV-SNP is active Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 19/42] x86/mm: Add support to validate memory when changing C-bit Brijesh Singh
2021-11-09 19:34   ` Borislav Petkov
2021-11-10 14:21     ` Brijesh Singh
2021-11-10 18:43       ` Borislav Petkov
2021-11-11 14:49         ` Tom Lendacky
2021-11-11 16:01           ` Borislav Petkov
2021-10-08 18:04 ` [PATCH v6 20/42] KVM: SVM: Define sev_features and vmpl field in the VMSA Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 21/42] KVM: SVM: Create a separate mapping for the SEV-ES save area Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 22/42] KVM: SVM: Create a separate mapping for the GHCB " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 23/42] KVM: SVM: Update the SEV-ES save area mapping Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 24/42] x86/sev: Use SEV-SNP AP creation to start secondary CPUs Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 25/42] x86/head: re-enable stack protection for 32/64-bit builds Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 26/42] x86/sev: move MSR-based VMGEXITs for CPUID to helper Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 27/42] KVM: x86: move lookup of indexed CPUID leafs " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 28/42] x86/compressed/acpi: move EFI system table lookup " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 29/42] x86/compressed/acpi: move EFI config " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 30/42] x86/compressed/acpi: move EFI vendor " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 31/42] x86/boot: Add Confidential Computing type to setup_data Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 32/42] x86/compressed/64: add support for SEV-SNP CPUID table in #VC handlers Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 33/42] boot/compressed/64: use firmware-validated CPUID for SEV-SNP guests Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 34/42] x86/boot: add a pointer to Confidential Computing blob in bootparams Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 35/42] x86/compressed/64: store Confidential Computing blob address " Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 36/42] x86/compressed/64: add identity mapping for Confidential Computing blob Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 37/42] x86/sev: use firmware-validated CPUID for SEV-SNP guests Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 38/42] x86/sev: Provide support for SNP guest request NAEs Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 39/42] x86/sev: Register SNP guest request platform device Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 40/42] virt: Add SEV-SNP guest driver Brijesh Singh
2021-10-10 17:51   ` Dov Murik
2021-10-13 11:37     ` Brijesh Singh
2021-10-20 21:33   ` Peter Gonda
2021-10-27 16:07     ` Brijesh Singh
2021-10-27 20:10       ` Peter Gonda [this message]
2021-10-27 20:47         ` Brijesh Singh
2021-10-27 21:05           ` Peter Gonda
2021-10-27 21:12             ` Brijesh Singh
2021-10-27 21:15               ` Peter Gonda
2021-10-08 18:04 ` [PATCH v6 41/42] virt: sevguest: Add support to derive key Brijesh Singh
2021-10-08 18:04 ` [PATCH v6 42/42] virt: sevguest: Add support to get extended report Brijesh Singh

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='CAMkAt6pCSNZiB7zVXp=70fF-qORZT0D5KCSY=GrJU0iiLZN_Mw@mail.gmail.com' \
    --to=pgonda@google.com \
    --cc=Thomas.Lendacky@amd.com \
    --cc=ak@linux.intel.com \
    --cc=ardb@kernel.org \
    --cc=bp@alien8.de \
    --cc=brijesh.singh@amd.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dgilbert@redhat.com \
    --cc=dovmurik@linux.ibm.com \
    --cc=hpa@zytor.com \
    --cc=jmattson@google.com \
    --cc=jroedel@suse.de \
    --cc=kirill@shutemov.name \
    --cc=kvm@vger.kernel.org \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@kernel.org \
    --cc=marcorr@google.com \
    --cc=michael.roth@amd.com \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=platform-driver-x86@vger.kernel.org \
    --cc=rientjes@google.com \
    --cc=sathyanarayanan.kuppuswamy@linux.intel.com \
    --cc=seanjc@google.com \
    --cc=slp@redhat.com \
    --cc=srinivas.pandruvada@linux.intel.com \
    --cc=tglx@linutronix.de \
    --cc=tobin@ibm.com \
    --cc=tony.luck@intel.com \
    --cc=vbabka@suse.cz \
    --cc=vkuznets@redhat.com \
    --cc=x86@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).