From: Peter Gonda <pgonda@google.com>
To: thomas.lendacky@amd.com
Cc: Peter Gonda <pgonda@google.com>,
Dionna Glaze <dionnaglaze@google.com>,
Borislav Petkov <bp@suse.de>, Michael Roth <michael.roth@amd.com>,
Haowen Bai <baihaowen@meizu.com>,
Yang Yingliang <yangyingliang@huawei.com>,
Marc Orr <marcorr@google.com>,
David Rientjes <rientjes@google.com>,
Ashish Kalra <Ashish.Kalra@amd.com>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Subject: [PATCH V4] virt: sev: Prevent IV reuse in SNP guest driver
Date: Thu, 3 Nov 2022 08:23:18 -0700 [thread overview]
Message-ID: <20221103152318.88354-1-pgonda@google.com> (raw)
The ASP and an SNP guest use a series of AES-GCM keys called VMPCKs to
communicate securely with each other. The IV to this scheme is a
sequence number that both the ASP and the guest track. Currently this
sequence number in a guest request must exactly match the sequence
number tracked by the ASP. This means that if the guest sees an error
from the host during a request it can only retry that exact request or
disable the VMPCK to prevent an IV reuse. AES-GCM cannot tolerate IV
reuse see:
https://csrc.nist.gov/csrc/media/projects/block-cipher-techniques/documents/bcm/comments/800-38-series-drafts/gcm/joux_comments.pdf
To handle userspace querying the cert_data length handle_guest_request()
now: saves the number of pages required by the host, retries the request
without requesting the extended data, then returns the number of pages
required.
Fixes: fce96cf044308 ("virt: Add SEV-SNP guest driver")
Signed-off-by: Peter Gonda <pgonda@google.com>
Reported-by: Peter Gonda <pgonda@google.com>
Cc: Dionna Glaze <dionnaglaze@google.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Michael Roth <michael.roth@amd.com>
Cc: Haowen Bai <baihaowen@meizu.com>
Cc: Yang Yingliang <yangyingliang@huawei.com>
Cc: Marc Orr <marcorr@google.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Ashish Kalra <Ashish.Kalra@amd.com>
Cc: linux-kernel@vger.kernel.org
Cc: kvm@vger.kernel.org
---
Tested by placing each of the guest requests: attestation quote,
extended attestation quote, and get key. Then tested the extended
attestation quote certificate length querying.
V4
* As suggested by Dionna moved the extended request retry logic into
the driver.
* Due to big change in patch dropped any reviewed-by tags.
---
drivers/virt/coco/sev-guest/sev-guest.c | 70 +++++++++++++++++++------
1 file changed, 53 insertions(+), 17 deletions(-)
diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index f422f9c58ba79..7dd6337ebdd5b 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -41,7 +41,7 @@ struct snp_guest_dev {
struct device *dev;
struct miscdevice misc;
- void *certs_data;
+ u8 (*certs_data)[SEV_FW_BLOB_MAX_SIZE];
struct snp_guest_crypto *crypto;
struct snp_guest_msg *request, *response;
struct snp_secrets_page_layout *layout;
@@ -67,8 +67,27 @@ static bool is_vmpck_empty(struct snp_guest_dev *snp_dev)
return true;
}
+/*
+ * If we receive an error from the host or ASP we have two options. We can
+ * either retry the exact same encrypted request or we can discontinue using the
+ * VMPCK.
+ *
+ * This is because in the current encryption scheme GHCB v2 uses AES-GCM to
+ * encrypt the requests. The IV for this scheme is the sequence number. GCM
+ * cannot tolerate IV reuse.
+ *
+ * The ASP FW v1.51 only increments the sequence numbers on a successful
+ * guest<->ASP back and forth and only accepts messages at its exact sequence
+ * number.
+ *
+ * So if we were to reuse the sequence number the encryption scheme is
+ * vulnerable. If we encrypt the sequence number for a fresh IV the ASP will
+ * reject our request.
+ */
static void snp_disable_vmpck(struct snp_guest_dev *snp_dev)
{
+ dev_alert(snp_dev->dev, "Disabling vmpck_id: %d to prevent IV reuse.\n",
+ vmpck_id);
memzero_explicit(snp_dev->vmpck, VMPCK_KEY_LEN);
snp_dev->vmpck = NULL;
}
@@ -323,32 +342,49 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
/* Call firmware to process the request */
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+
+ /*
+ * If the extended guest request fails due to having to small of a
+ * certificate data buffer retry the same guest request without the
+ * extended data request.
+ */
+ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
+ err == SNP_GUEST_REQ_INVALID_LEN) {
+ const unsigned int certs_npages = snp_dev->input.data_npages;
+
+ exit_code = SVM_VMGEXIT_GUEST_REQUEST;
+ rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+
+ err = SNP_GUEST_REQ_INVALID_LEN;
+ snp_dev->input.data_npages = certs_npages;
+ }
+
if (fw_err)
*fw_err = err;
- if (rc)
- return rc;
+ if (rc) {
+ dev_alert(snp_dev->dev,
+ "Detected error from ASP request. rc: %d, fw_err: %llu\n",
+ rc, *fw_err);
+ goto disable_vmpck;
+ }
- /*
- * The verify_and_dec_payload() will fail only if the hypervisor is
- * actively modifying the message header or corrupting the encrypted payload.
- * This hints that hypervisor is acting in a bad faith. Disable the VMPCK so that
- * the key cannot be used for any communication. The key is disabled to ensure
- * that AES-GCM does not use the same IV while encrypting the request payload.
- */
rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz);
if (rc) {
dev_alert(snp_dev->dev,
- "Detected unexpected decode failure, disabling the vmpck_id %d\n",
- vmpck_id);
- snp_disable_vmpck(snp_dev);
- return rc;
+ "Detected unexpected decode failure from ASP. rc: %d\n",
+ rc);
+ goto disable_vmpck;
}
/* Increment to new message sequence after payload decryption was successful. */
snp_inc_msg_seqno(snp_dev);
return 0;
+
+disable_vmpck:
+ snp_disable_vmpck(snp_dev);
+ return rc;
}
static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
@@ -676,7 +712,7 @@ static int __init sev_guest_probe(struct platform_device *pdev)
if (!snp_dev->response)
goto e_free_request;
- snp_dev->certs_data = alloc_shared_pages(dev, SEV_FW_BLOB_MAX_SIZE);
+ snp_dev->certs_data = alloc_shared_pages(dev, sizeof(*snp_dev->certs_data));
if (!snp_dev->certs_data)
goto e_free_response;
@@ -703,7 +739,7 @@ static int __init sev_guest_probe(struct platform_device *pdev)
return 0;
e_free_cert_data:
- free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE);
+ free_shared_pages(snp_dev->certs_data, sizeof(*snp_dev->certs_data));
e_free_response:
free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg));
e_free_request:
@@ -717,7 +753,7 @@ static int __exit sev_guest_remove(struct platform_device *pdev)
{
struct snp_guest_dev *snp_dev = platform_get_drvdata(pdev);
- free_shared_pages(snp_dev->certs_data, SEV_FW_BLOB_MAX_SIZE);
+ free_shared_pages(snp_dev->certs_data, sizeof(*snp_dev->certs_data));
free_shared_pages(snp_dev->response, sizeof(struct snp_guest_msg));
free_shared_pages(snp_dev->request, sizeof(struct snp_guest_msg));
deinit_crypto(snp_dev->crypto);
--
2.38.1.273.g43a17bfeac-goog
next reply other threads:[~2022-11-03 15:23 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-03 15:23 Peter Gonda [this message]
2022-11-04 17:39 ` [PATCH V4] virt: sev: Prevent IV reuse in SNP guest driver Tom Lendacky
2022-11-11 16:46 ` Borislav Petkov
2022-11-14 21:11 ` Peter Gonda
2022-11-15 21:36 ` Borislav Petkov
2022-11-15 21:48 ` Peter Gonda
2022-11-15 21:47 ` Peter Gonda
2022-11-16 12:20 ` Borislav Petkov
2022-11-16 16:23 ` Peter Gonda
2022-11-16 16:58 ` Tom Lendacky
2022-11-16 17:10 ` Peter Gonda
2022-11-16 17:28 ` Borislav Petkov
2022-11-16 17:57 ` Peter Gonda
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=20221103152318.88354-1-pgonda@google.com \
--to=pgonda@google.com \
--cc=Ashish.Kalra@amd.com \
--cc=baihaowen@meizu.com \
--cc=bp@suse.de \
--cc=dionnaglaze@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marcorr@google.com \
--cc=michael.roth@amd.com \
--cc=rientjes@google.com \
--cc=thomas.lendacky@amd.com \
--cc=yangyingliang@huawei.com \
/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.