virt: sevguest: Add support to derive key

The SNP_GET_DERIVED_KEY ioctl interface can be used by the SNP guest to
ask the firmware to provide a key derived from a root key. The derived
key may be used by the guest for any purposes it chooses, such as a
sealing key or communicating with the external entities.

See SEV-SNP firmware spec for more information.

  [ bp: No need to memset "req" - it will get overwritten. ]

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
Link: https://lore.kernel.org/r/20220307213356.2797205-45-brijesh.singh@amd.com
This commit is contained in:
Brijesh Singh 2022-02-24 10:56:23 -06:00 committed by Borislav Petkov
parent fce96cf044
commit 68de0b2f93
3 changed files with 79 additions and 0 deletions

View File

@ -77,6 +77,23 @@ On success, the snp_report_resp.data will contains the report. The report
contain the format described in the SEV-SNP specification. See the SEV-SNP
specification for further details.
2.2 SNP_GET_DERIVED_KEY
-----------------------
:Technology: sev-snp
:Type: guest ioctl
:Parameters (in): struct snp_derived_key_req
:Returns (out): struct snp_derived_key_resp on success, -negative on error
The SNP_GET_DERIVED_KEY ioctl can be used to get a key derive from a root key.
The derived key can be used by the guest for any purpose, such as sealing keys
or communicating with external entities.
The ioctl uses the SNP_GUEST_REQUEST (MSG_KEY_REQ) command provided by the
SEV-SNP firmware to derive the key. See SEV-SNP specification for further details
on the various fields passed in the key derivation request.
On success, the snp_derived_key_resp.data contains the derived key value. See
the SEV-SNP specification for further details.
Reference
---------

View File

@ -391,6 +391,48 @@ e_free:
return rc;
}
static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg)
{
struct snp_guest_crypto *crypto = snp_dev->crypto;
struct snp_derived_key_resp resp = {0};
struct snp_derived_key_req req;
int rc, resp_len;
/* Response data is 64 bytes and max authsize for GCM is 16 bytes. */
u8 buf[64 + 16];
lockdep_assert_held(&snp_cmd_mutex);
if (!arg->req_data || !arg->resp_data)
return -EINVAL;
/*
* The intermediate response buffer is used while decrypting the
* response payload. Make sure that it has enough space to cover the
* authtag.
*/
resp_len = sizeof(resp.data) + crypto->a_len;
if (sizeof(buf) < resp_len)
return -ENOMEM;
if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req)))
return -EFAULT;
rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version,
SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len,
&arg->fw_err);
if (rc)
return rc;
memcpy(resp.data, buf, sizeof(resp.data));
if (copy_to_user((void __user *)arg->resp_data, &resp, sizeof(resp)))
rc = -EFAULT;
/* The response buffer contains the sensitive data, explicitly clear it. */
memzero_explicit(buf, sizeof(buf));
memzero_explicit(&resp, sizeof(resp));
return rc;
}
static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
{
struct snp_guest_dev *snp_dev = to_snp_dev(file);
@ -420,6 +462,9 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long
case SNP_GET_REPORT:
ret = get_report(snp_dev, &input);
break;
case SNP_GET_DERIVED_KEY:
ret = get_derived_key(snp_dev, &input);
break;
default:
break;
}

View File

@ -30,6 +30,20 @@ struct snp_report_resp {
__u8 data[4000];
};
struct snp_derived_key_req {
__u32 root_key_select;
__u32 rsvd;
__u64 guest_field_select;
__u32 vmpl;
__u32 guest_svn;
__u64 tcb_version;
};
struct snp_derived_key_resp {
/* response data, see SEV-SNP spec for the format */
__u8 data[64];
};
struct snp_guest_request_ioctl {
/* message version number (must be non-zero) */
__u8 msg_version;
@ -47,4 +61,7 @@ struct snp_guest_request_ioctl {
/* Get SNP attestation report */
#define SNP_GET_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x0, struct snp_guest_request_ioctl)
/* Get a derived key from the root */
#define SNP_GET_DERIVED_KEY _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x1, struct snp_guest_request_ioctl)
#endif /* __UAPI_LINUX_SEV_GUEST_H_ */