From: Brijesh Singh <brijesh.singh@amd.com>
To: qemu-devel@nongnu.org
Cc: Brijesh Singh <brijesh.singh@amd.com>,
James Bottomley <jejb@linux.ibm.com>,
Tom Lendacky <Thomas.Lendacky@amd.com>,
Eric Blake <eblake@redhat.com>,
Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org
Subject: [PATCH] target/i386/sev: add the support to query the attestation report
Date: Fri, 4 Dec 2020 15:31:01 -0600 [thread overview]
Message-ID: <20201204213101.14552-1-brijesh.singh@amd.com> (raw)
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
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
| 8 ++++++
qapi/misc-target.json | 38 +++++++++++++++++++++++++++
target/i386/monitor.c | 6 +++++
target/i386/sev-stub.c | 7 +++++
target/i386/sev.c | 54 +++++++++++++++++++++++++++++++++++++++
target/i386/sev_i386.h | 2 ++
6 files changed, 115 insertions(+)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 56ce14ad20..6d0f8101ba 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1585,6 +1585,8 @@ enum sev_cmd_id {
KVM_SEV_DBG_ENCRYPT,
/* Guest certificates commands */
KVM_SEV_CERT_EXPORT,
+ /* Attestation report */
+ KVM_SEV_GET_ATTESTATION_REPORT,
KVM_SEV_NR_MAX,
};
@@ -1637,6 +1639,12 @@ struct kvm_sev_dbg {
__u32 len;
};
+struct kvm_sev_attestation_report {
+ __u8 mnonce[16];
+ __u64 uaddr;
+ __u32 len;
+};
+
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 1e561fa97b..ec6565e6ef 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -267,3 +267,41 @@
##
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
'if': 'defined(TARGET_ARM)' }
+
+
+##
+# @SevAttestationReport:
+#
+# The struct describes attestation report for a Secure Encrypted Virtualization
+# feature.
+#
+# @data: guest attestation report (base64 encoded)
+#
+#
+# Since: 5.2
+##
+{ 'struct': 'SevAttestationReport',
+ 'data': { 'data': 'str'},
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-attestation-report:
+#
+# This command is used to get the SEV attestation report, and is supported on AMD
+# X86 platforms only.
+#
+# @mnonce: a random 16 bytes of data (it will be included in report)
+#
+# Returns: SevAttestationReport objects.
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute" : "query-sev-attestation-report", "arguments": { "mnonce": "aaaaaaa" } }
+# <- { "return" : { "data": "aaaaaaaabbbddddd"} }
+#
+##
+{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
+ 'returns': 'SevAttestationReport',
+ 'if': 'defined(TARGET_I386)' }
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 9f9e1c42f4..a4b65f330c 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -729,3 +729,9 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
{
return sev_get_capabilities(errp);
}
+
+SevAttestationReport *
+qmp_query_sev_attestation_report(const char *mnonce, Error **errp)
+{
+ return sev_get_attestation_report(mnonce, errp);
+}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
index 88e3f39a1e..66d16f53d8 100644
--- a/target/i386/sev-stub.c
+++ b/target/i386/sev-stub.c
@@ -49,3 +49,10 @@ SevCapability *sev_get_capabilities(Error **errp)
error_setg(errp, "SEV is not available in this QEMU");
return NULL;
}
+
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 93c4d60b82..28958fb71b 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -68,6 +68,7 @@ struct SevGuestState {
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
#define DEFAULT_SEV_DEVICE "/dev/sev"
+#define DEFAULT_ATTESATION_REPORT_BUF_SIZE 4096
static SevGuestState *sev_guest;
static Error *sev_mig_blocker;
@@ -490,6 +491,59 @@ out:
return cap;
}
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+ struct kvm_sev_attestation_report input = {};
+ SevGuestState *sev = sev_guest;
+ SevAttestationReport *report;
+ guchar *data;
+ int err = 0, ret;
+
+ if (!sev_enabled()) {
+ error_setg(errp, "SEV is not enabled");
+ return NULL;
+ }
+
+ /* Verify that user provided random data length */
+ if (strlen(mnonce) != sizeof(input.mnonce)) {
+ error_setg(errp, "Expected mnonce data len %ld got %ld",
+ sizeof(input.mnonce), strlen(mnonce));
+ 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));
+ return NULL;
+ }
+ }
+
+ data = g_malloc(input.len);
+ input.uaddr = (unsigned long)data;
+ memcpy(input.mnonce, mnonce, 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);
+
+e_free_data:
+ g_free(data);
+ return report;
+}
+
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{
diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h
index 4db6960f60..e2d0774708 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev_i386.h
@@ -35,5 +35,7 @@ extern uint32_t sev_get_cbit_position(void);
extern uint32_t sev_get_reduced_phys_bits(void);
extern char *sev_get_launch_measurement(void);
extern SevCapability *sev_get_capabilities(Error **errp);
+extern SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp);
#endif
--
2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Brijesh Singh <brijesh.singh@amd.com>
To: qemu-devel@nongnu.org
Cc: Tom Lendacky <Thomas.Lendacky@amd.com>,
Brijesh Singh <brijesh.singh@amd.com>,
kvm@vger.kernel.org, James Bottomley <jejb@linux.ibm.com>,
Paolo Bonzini <pbonzini@redhat.com>
Subject: [PATCH] target/i386/sev: add the support to query the attestation report
Date: Fri, 4 Dec 2020 15:31:01 -0600 [thread overview]
Message-ID: <20201204213101.14552-1-brijesh.singh@amd.com> (raw)
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
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
| 8 ++++++
qapi/misc-target.json | 38 +++++++++++++++++++++++++++
target/i386/monitor.c | 6 +++++
target/i386/sev-stub.c | 7 +++++
target/i386/sev.c | 54 +++++++++++++++++++++++++++++++++++++++
target/i386/sev_i386.h | 2 ++
6 files changed, 115 insertions(+)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 56ce14ad20..6d0f8101ba 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1585,6 +1585,8 @@ enum sev_cmd_id {
KVM_SEV_DBG_ENCRYPT,
/* Guest certificates commands */
KVM_SEV_CERT_EXPORT,
+ /* Attestation report */
+ KVM_SEV_GET_ATTESTATION_REPORT,
KVM_SEV_NR_MAX,
};
@@ -1637,6 +1639,12 @@ struct kvm_sev_dbg {
__u32 len;
};
+struct kvm_sev_attestation_report {
+ __u8 mnonce[16];
+ __u64 uaddr;
+ __u32 len;
+};
+
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index 1e561fa97b..ec6565e6ef 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -267,3 +267,41 @@
##
{ 'command': 'query-gic-capabilities', 'returns': ['GICCapability'],
'if': 'defined(TARGET_ARM)' }
+
+
+##
+# @SevAttestationReport:
+#
+# The struct describes attestation report for a Secure Encrypted Virtualization
+# feature.
+#
+# @data: guest attestation report (base64 encoded)
+#
+#
+# Since: 5.2
+##
+{ 'struct': 'SevAttestationReport',
+ 'data': { 'data': 'str'},
+ 'if': 'defined(TARGET_I386)' }
+
+##
+# @query-sev-attestation-report:
+#
+# This command is used to get the SEV attestation report, and is supported on AMD
+# X86 platforms only.
+#
+# @mnonce: a random 16 bytes of data (it will be included in report)
+#
+# Returns: SevAttestationReport objects.
+#
+# Since: 5.2
+#
+# Example:
+#
+# -> { "execute" : "query-sev-attestation-report", "arguments": { "mnonce": "aaaaaaa" } }
+# <- { "return" : { "data": "aaaaaaaabbbddddd"} }
+#
+##
+{ 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' },
+ 'returns': 'SevAttestationReport',
+ 'if': 'defined(TARGET_I386)' }
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 9f9e1c42f4..a4b65f330c 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -729,3 +729,9 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
{
return sev_get_capabilities(errp);
}
+
+SevAttestationReport *
+qmp_query_sev_attestation_report(const char *mnonce, Error **errp)
+{
+ return sev_get_attestation_report(mnonce, errp);
+}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
index 88e3f39a1e..66d16f53d8 100644
--- a/target/i386/sev-stub.c
+++ b/target/i386/sev-stub.c
@@ -49,3 +49,10 @@ SevCapability *sev_get_capabilities(Error **errp)
error_setg(errp, "SEV is not available in this QEMU");
return NULL;
}
+
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+ error_setg(errp, "SEV is not available in this QEMU");
+ return NULL;
+}
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 93c4d60b82..28958fb71b 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -68,6 +68,7 @@ struct SevGuestState {
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
#define DEFAULT_SEV_DEVICE "/dev/sev"
+#define DEFAULT_ATTESATION_REPORT_BUF_SIZE 4096
static SevGuestState *sev_guest;
static Error *sev_mig_blocker;
@@ -490,6 +491,59 @@ out:
return cap;
}
+SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp)
+{
+ struct kvm_sev_attestation_report input = {};
+ SevGuestState *sev = sev_guest;
+ SevAttestationReport *report;
+ guchar *data;
+ int err = 0, ret;
+
+ if (!sev_enabled()) {
+ error_setg(errp, "SEV is not enabled");
+ return NULL;
+ }
+
+ /* Verify that user provided random data length */
+ if (strlen(mnonce) != sizeof(input.mnonce)) {
+ error_setg(errp, "Expected mnonce data len %ld got %ld",
+ sizeof(input.mnonce), strlen(mnonce));
+ 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));
+ return NULL;
+ }
+ }
+
+ data = g_malloc(input.len);
+ input.uaddr = (unsigned long)data;
+ memcpy(input.mnonce, mnonce, 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);
+
+e_free_data:
+ g_free(data);
+ return report;
+}
+
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{
diff --git a/target/i386/sev_i386.h b/target/i386/sev_i386.h
index 4db6960f60..e2d0774708 100644
--- a/target/i386/sev_i386.h
+++ b/target/i386/sev_i386.h
@@ -35,5 +35,7 @@ extern uint32_t sev_get_cbit_position(void);
extern uint32_t sev_get_reduced_phys_bits(void);
extern char *sev_get_launch_measurement(void);
extern SevCapability *sev_get_capabilities(Error **errp);
+extern SevAttestationReport *
+sev_get_attestation_report(const char *mnonce, Error **errp);
#endif
--
2.17.1
next reply other threads:[~2020-12-04 21:32 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-04 21:31 Brijesh Singh [this message]
2020-12-04 21:31 ` [PATCH] target/i386/sev: add the support to query the attestation report Brijesh Singh
2020-12-10 16:13 ` James Bottomley
2020-12-10 16:13 ` James Bottomley
2020-12-11 13:23 ` Brijesh Singh
2020-12-11 13:23 ` Brijesh Singh
2020-12-13 20:28 ` Dov Murik
2020-12-13 20:28 ` Dov Murik
2021-01-14 18:34 ` Dr. David Alan Gilbert
2021-01-14 18:34 ` Dr. David Alan Gilbert
2021-01-19 16:45 ` Eric Blake
2021-01-19 16:45 ` Eric Blake
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=20201204213101.14552-1-brijesh.singh@amd.com \
--to=brijesh.singh@amd.com \
--cc=Thomas.Lendacky@amd.com \
--cc=eblake@redhat.com \
--cc=jejb@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--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.