Commit 332d2c1d authored by Michael Roth's avatar Michael Roth Committed by Paolo Bonzini

crypto: ccp: Add the SNP_VLEK_LOAD command

When requesting an attestation report a guest is able to specify whether
it wants SNP firmware to sign the report using either a Versioned Chip
Endorsement Key (VCEK), which is derived from chip-unique secrets, or a
Versioned Loaded Endorsement Key (VLEK) which is obtained from an AMD
Key Derivation Service (KDS) and derived from seeds allocated to
enrolled cloud service providers (CSPs).

For VLEK keys, an SNP_VLEK_LOAD SNP firmware command is used to load
them into the system after obtaining them from the KDS. Add a
corresponding userspace interface so to allow the loading of VLEK keys
into the system.

See SEV-SNP Firmware ABI 1.54, SNP_VLEK_LOAD for more details.
Reviewed-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarMichael Roth <michael.roth@amd.com>
Message-ID: <20240501085210.2213060-21-michael.roth@amd.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 5d766508
...@@ -176,6 +176,25 @@ to SNP_CONFIG command defined in the SEV-SNP spec. The current values of ...@@ -176,6 +176,25 @@ to SNP_CONFIG command defined in the SEV-SNP spec. The current values of
the firmware parameters affected by this command can be queried via the firmware parameters affected by this command can be queried via
SNP_PLATFORM_STATUS. SNP_PLATFORM_STATUS.
2.7 SNP_VLEK_LOAD
-----------------
:Technology: sev-snp
:Type: hypervisor ioctl cmd
:Parameters (in): struct sev_user_data_snp_vlek_load
:Returns (out): 0 on success, -negative on error
When requesting an attestation report a guest is able to specify whether
it wants SNP firmware to sign the report using either a Versioned Chip
Endorsement Key (VCEK), which is derived from chip-unique secrets, or a
Versioned Loaded Endorsement Key (VLEK) which is obtained from an AMD
Key Derivation Service (KDS) and derived from seeds allocated to
enrolled cloud service providers.
In the case of VLEK keys, the SNP_VLEK_LOAD SNP command is used to load
them into the system after obtaining them from the KDS, and corresponds
closely to the SNP_VLEK_LOAD firmware command specified in the SEV-SNP
spec.
3. SEV-SNP CPUID Enforcement 3. SEV-SNP CPUID Enforcement
============================ ============================
......
...@@ -2027,6 +2027,39 @@ static int sev_ioctl_do_snp_set_config(struct sev_issue_cmd *argp, bool writable ...@@ -2027,6 +2027,39 @@ static int sev_ioctl_do_snp_set_config(struct sev_issue_cmd *argp, bool writable
return __sev_do_cmd_locked(SEV_CMD_SNP_CONFIG, &config, &argp->error); return __sev_do_cmd_locked(SEV_CMD_SNP_CONFIG, &config, &argp->error);
} }
static int sev_ioctl_do_snp_vlek_load(struct sev_issue_cmd *argp, bool writable)
{
struct sev_device *sev = psp_master->sev_data;
struct sev_user_data_snp_vlek_load input;
void *blob;
int ret;
if (!sev->snp_initialized || !argp->data)
return -EINVAL;
if (!writable)
return -EPERM;
if (copy_from_user(&input, u64_to_user_ptr(argp->data), sizeof(input)))
return -EFAULT;
if (input.len != sizeof(input) || input.vlek_wrapped_version != 0)
return -EINVAL;
blob = psp_copy_user_blob(input.vlek_wrapped_address,
sizeof(struct sev_user_data_snp_wrapped_vlek_hashstick));
if (IS_ERR(blob))
return PTR_ERR(blob);
input.vlek_wrapped_address = __psp_pa(blob);
ret = __sev_do_cmd_locked(SEV_CMD_SNP_VLEK_LOAD, &input, &argp->error);
kfree(blob);
return ret;
}
static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -2087,6 +2120,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) ...@@ -2087,6 +2120,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
case SNP_SET_CONFIG: case SNP_SET_CONFIG:
ret = sev_ioctl_do_snp_set_config(&input, writable); ret = sev_ioctl_do_snp_set_config(&input, writable);
break; break;
case SNP_VLEK_LOAD:
ret = sev_ioctl_do_snp_vlek_load(&input, writable);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
......
...@@ -31,6 +31,7 @@ enum { ...@@ -31,6 +31,7 @@ enum {
SNP_PLATFORM_STATUS, SNP_PLATFORM_STATUS,
SNP_COMMIT, SNP_COMMIT,
SNP_SET_CONFIG, SNP_SET_CONFIG,
SNP_VLEK_LOAD,
SEV_MAX, SEV_MAX,
}; };
...@@ -214,6 +215,32 @@ struct sev_user_data_snp_config { ...@@ -214,6 +215,32 @@ struct sev_user_data_snp_config {
__u8 rsvd1[52]; __u8 rsvd1[52];
} __packed; } __packed;
/**
* struct sev_data_snp_vlek_load - SNP_VLEK_LOAD structure
*
* @len: length of the command buffer read by the PSP
* @vlek_wrapped_version: version of wrapped VLEK hashstick (Must be 0h)
* @rsvd: reserved
* @vlek_wrapped_address: address of a wrapped VLEK hashstick
* (struct sev_user_data_snp_wrapped_vlek_hashstick)
*/
struct sev_user_data_snp_vlek_load {
__u32 len; /* In */
__u8 vlek_wrapped_version; /* In */
__u8 rsvd[3]; /* In */
__u64 vlek_wrapped_address; /* In */
} __packed;
/**
* struct sev_user_data_snp_vlek_wrapped_vlek_hashstick - Wrapped VLEK data
*
* @data: Opaque data provided by AMD KDS (as described in SEV-SNP Firmware ABI
* 1.54, SNP_VLEK_LOAD)
*/
struct sev_user_data_snp_wrapped_vlek_hashstick {
__u8 data[432]; /* In */
} __packed;
/** /**
* struct sev_issue_cmd - SEV ioctl parameters * struct sev_issue_cmd - SEV ioctl parameters
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment