aboutsummaryrefslogtreecommitdiff
path: root/target/i386/sev.c
diff options
context:
space:
mode:
authorBrijesh Singh <brijesh.singh@amd.com>2021-04-29 12:07:28 -0500
committerEduardo Habkost <ehabkost@redhat.com>2021-06-01 09:32:23 -0400
commit3ea1a80243d5b5ba23d8c2b7d3a86034ea0ade22 (patch)
tree9cd64f57fe932e5e34ac83a215339c1d2308472f /target/i386/sev.c
parent5aa9ef5e4bb8194e66c4b62d8fe7ef8392786a9f (diff)
target/i386/sev: add support to query the attestation report
The SEV FW >= 0.23 added a new command that can be used to query the attestation report containing the SHA-256 digest of the guest memory and VMSA encrypted with the LAUNCH_UPDATE and sign it with the PEK. Note, we already have a command (LAUNCH_MEASURE) that can be used to query the SHA-256 digest of the guest memory encrypted through the LAUNCH_UPDATE. The main difference between previous and this command is that the report is signed with the PEK and unlike the LAUNCH_MEASURE command the ATTESATION_REPORT command can be called while the guest is running. Add a QMP interface "query-sev-attestation-report" that can be used to get the report encoded in base64. Cc: James Bottomley <jejb@linux.ibm.com> Cc: Tom Lendacky <Thomas.Lendacky@amd.com> Cc: Eric Blake <eblake@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: kvm@vger.kernel.org Reviewed-by: James Bottomley <jejb@linux.ibm.com> Tested-by: James Bottomley <jejb@linux.ibm.com> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Connor Kuehl <ckuehl@redhat.com> Message-Id: <20210429170728.24322-1-brijesh.singh@amd.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'target/i386/sev.c')
-rw-r--r--target/i386/sev.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 41f7800b5f..1a88f12703 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -492,6 +492,73 @@ out:
return cap;
}
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+ struct kvm_sev_attestation_report input = {};
+ SevAttestationReport *report = NULL;
+ SevGuestState *sev = sev_guest;
+ guchar *data;
+ guchar *buf;
+ gsize len;
+ int err = 0, ret;
+
+ if (!sev_enabled()) {
+ error_setg(errp, "SEV is not enabled");
+ return NULL;
+ }
+
+ /* lets decode the mnonce string */
+ buf = g_base64_decode(mnonce, &len);
+ if (!buf) {
+ error_setg(errp, "SEV: failed to decode mnonce input");
+ return NULL;
+ }
+
+ /* verify the input mnonce length */
+ if (len != sizeof(input.mnonce)) {
+ error_setg(errp, "SEV: mnonce must be %zu bytes (got %" G_GSIZE_FORMAT ")",
+ sizeof(input.mnonce), len);
+ g_free(buf);
+ return NULL;
+ }
+
+ /* Query the report length */
+ ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
+ &input, &err);
+ if (ret < 0) {
+ if (err != SEV_RET_INVALID_LEN) {
+ error_setg(errp, "failed to query the attestation report length "
+ "ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
+ g_free(buf);
+ return NULL;
+ }
+ }
+
+ data = g_malloc(input.len);
+ input.uaddr = (unsigned long)data;
+ memcpy(input.mnonce, buf, sizeof(input.mnonce));
+
+ /* Query the report */
+ ret = sev_ioctl(sev->sev_fd, KVM_SEV_GET_ATTESTATION_REPORT,
+ &input, &err);
+ if (ret) {
+ error_setg_errno(errp, errno, "Failed to get attestation report"
+ " ret=%d fw_err=%d (%s)", ret, err, fw_error_to_str(err));
+ goto e_free_data;
+ }
+
+ report = g_new0(SevAttestationReport, 1);
+ report->data = g_base64_encode(data, input.len);
+
+ trace_kvm_sev_attestation_report(mnonce, report->data);
+
+e_free_data:
+ g_free(data);
+ g_free(buf);
+ return report;
+}
+
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{