Skip to content

Commit 2c07ded

Browse files
codomaniabonzini
authored andcommitted
KVM/SVM: add support for SEV attestation command
The SEV FW version >= 0.23 added a new command that can be used to query the attestation report containing the SHA-256 digest of the guest memory encrypted through the KVM_SEV_LAUNCH_UPDATE_{DATA, VMSA} commands and sign the report with the Platform Endorsement Key (PEK). See the SEV FW API spec section 6.8 for more details. Note there already exist a command (KVM_SEV_LAUNCH_MEASURE) that can be used to get the SHA-256 digest. The main difference between the KVM_SEV_LAUNCH_MEASURE and KVM_SEV_ATTESTATION_REPORT is that the latter can be called while the guest is running and the measurement value is signed with PEK. Cc: James Bottomley <[email protected]> Cc: Tom Lendacky <[email protected]> Cc: David Rientjes <[email protected]> Cc: Paolo Bonzini <[email protected]> Cc: Sean Christopherson <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: John Allen <[email protected]> Cc: Herbert Xu <[email protected]> Cc: [email protected] Reviewed-by: Tom Lendacky <[email protected]> Acked-by: David Rientjes <[email protected]> Tested-by: James Bottomley <[email protected]> Signed-off-by: Brijesh Singh <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent c1d1650 commit 2c07ded

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed

Documentation/virt/kvm/amd-memory-encryption.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,27 @@ Returns: 0 on success, -negative on error
263263
__u32 trans_len;
264264
};
265265

266+
10. KVM_SEV_GET_ATTESTATION_REPORT
267+
----------------------------------
268+
269+
The KVM_SEV_GET_ATTESTATION_REPORT command can be used by the hypervisor to query the attestation
270+
report containing the SHA-256 digest of the guest memory and VMSA passed through the KVM_SEV_LAUNCH
271+
commands and signed with the PEK. The digest returned by the command should match the digest
272+
used by the guest owner with the KVM_SEV_LAUNCH_MEASURE.
273+
274+
Parameters (in): struct kvm_sev_attestation
275+
276+
Returns: 0 on success, -negative on error
277+
278+
::
279+
280+
struct kvm_sev_attestation_report {
281+
__u8 mnonce[16]; /* A random mnonce that will be placed in the report */
282+
283+
__u64 uaddr; /* userspace address where the report should be copied */
284+
__u32 len;
285+
};
286+
266287
References
267288
==========
268289

arch/x86/kvm/svm/sev.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,74 @@ static int sev_launch_secret(struct kvm *kvm, struct kvm_sev_cmd *argp)
10411041
return ret;
10421042
}
10431043

1044+
static int sev_get_attestation_report(struct kvm *kvm, struct kvm_sev_cmd *argp)
1045+
{
1046+
void __user *report = (void __user *)(uintptr_t)argp->data;
1047+
struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
1048+
struct sev_data_attestation_report *data;
1049+
struct kvm_sev_attestation_report params;
1050+
void __user *p;
1051+
void *blob = NULL;
1052+
int ret;
1053+
1054+
if (!sev_guest(kvm))
1055+
return -ENOTTY;
1056+
1057+
if (copy_from_user(&params, (void __user *)(uintptr_t)argp->data, sizeof(params)))
1058+
return -EFAULT;
1059+
1060+
data = kzalloc(sizeof(*data), GFP_KERNEL_ACCOUNT);
1061+
if (!data)
1062+
return -ENOMEM;
1063+
1064+
/* User wants to query the blob length */
1065+
if (!params.len)
1066+
goto cmd;
1067+
1068+
p = (void __user *)(uintptr_t)params.uaddr;
1069+
if (p) {
1070+
if (params.len > SEV_FW_BLOB_MAX_SIZE) {
1071+
ret = -EINVAL;
1072+
goto e_free;
1073+
}
1074+
1075+
ret = -ENOMEM;
1076+
blob = kmalloc(params.len, GFP_KERNEL);
1077+
if (!blob)
1078+
goto e_free;
1079+
1080+
data->address = __psp_pa(blob);
1081+
data->len = params.len;
1082+
memcpy(data->mnonce, params.mnonce, sizeof(params.mnonce));
1083+
}
1084+
cmd:
1085+
data->handle = sev->handle;
1086+
ret = sev_issue_cmd(kvm, SEV_CMD_ATTESTATION_REPORT, data, &argp->error);
1087+
/*
1088+
* If we query the session length, FW responded with expected data.
1089+
*/
1090+
if (!params.len)
1091+
goto done;
1092+
1093+
if (ret)
1094+
goto e_free_blob;
1095+
1096+
if (blob) {
1097+
if (copy_to_user(p, blob, params.len))
1098+
ret = -EFAULT;
1099+
}
1100+
1101+
done:
1102+
params.len = data->len;
1103+
if (copy_to_user(report, &params, sizeof(params)))
1104+
ret = -EFAULT;
1105+
e_free_blob:
1106+
kfree(blob);
1107+
e_free:
1108+
kfree(data);
1109+
return ret;
1110+
}
1111+
10441112
int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
10451113
{
10461114
struct kvm_sev_cmd sev_cmd;
@@ -1091,6 +1159,9 @@ int svm_mem_enc_op(struct kvm *kvm, void __user *argp)
10911159
case KVM_SEV_LAUNCH_SECRET:
10921160
r = sev_launch_secret(kvm, &sev_cmd);
10931161
break;
1162+
case KVM_SEV_GET_ATTESTATION_REPORT:
1163+
r = sev_get_attestation_report(kvm, &sev_cmd);
1164+
break;
10941165
default:
10951166
r = -EINVAL;
10961167
goto out;

drivers/crypto/ccp/sev-dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ static int sev_cmd_buffer_len(int cmd)
128128
case SEV_CMD_LAUNCH_UPDATE_SECRET: return sizeof(struct sev_data_launch_secret);
129129
case SEV_CMD_DOWNLOAD_FIRMWARE: return sizeof(struct sev_data_download_firmware);
130130
case SEV_CMD_GET_ID: return sizeof(struct sev_data_get_id);
131+
case SEV_CMD_ATTESTATION_REPORT: return sizeof(struct sev_data_attestation_report);
131132
default: return 0;
132133
}
133134

include/linux/psp-sev.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ enum sev_cmd {
6666
SEV_CMD_LAUNCH_MEASURE = 0x033,
6767
SEV_CMD_LAUNCH_UPDATE_SECRET = 0x034,
6868
SEV_CMD_LAUNCH_FINISH = 0x035,
69+
SEV_CMD_ATTESTATION_REPORT = 0x036,
6970

7071
/* Guest migration commands (outgoing) */
7172
SEV_CMD_SEND_START = 0x040,
@@ -483,6 +484,22 @@ struct sev_data_dbg {
483484
u32 len; /* In */
484485
} __packed;
485486

487+
/**
488+
* struct sev_data_attestation_report - SEV_ATTESTATION_REPORT command parameters
489+
*
490+
* @handle: handle of the VM
491+
* @mnonce: a random nonce that will be included in the report.
492+
* @address: physical address where the report will be copied.
493+
* @len: length of the physical buffer.
494+
*/
495+
struct sev_data_attestation_report {
496+
u32 handle; /* In */
497+
u32 reserved;
498+
u64 address; /* In */
499+
u8 mnonce[16]; /* In */
500+
u32 len; /* In/Out */
501+
} __packed;
502+
486503
#ifdef CONFIG_CRYPTO_DEV_SP_PSP
487504

488505
/**

include/uapi/linux/kvm.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,8 @@ enum sev_cmd_id {
15931593
KVM_SEV_DBG_ENCRYPT,
15941594
/* Guest certificates commands */
15951595
KVM_SEV_CERT_EXPORT,
1596+
/* Attestation report */
1597+
KVM_SEV_GET_ATTESTATION_REPORT,
15961598

15971599
KVM_SEV_NR_MAX,
15981600
};
@@ -1645,6 +1647,12 @@ struct kvm_sev_dbg {
16451647
__u32 len;
16461648
};
16471649

1650+
struct kvm_sev_attestation_report {
1651+
__u8 mnonce[16];
1652+
__u64 uaddr;
1653+
__u32 len;
1654+
};
1655+
16481656
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
16491657
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
16501658
#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2)

0 commit comments

Comments
 (0)