244 lines
9.3 KiB
ReStructuredText
244 lines
9.3 KiB
ReStructuredText
|
.. SPDX-License-Identifier: GPL-2.0
|
||
|
|
||
|
===================================================================
|
||
|
The Definitive SEV Guest API Documentation
|
||
|
===================================================================
|
||
|
|
||
|
1. General description
|
||
|
======================
|
||
|
|
||
|
The SEV API is a set of ioctls that are used by the guest or hypervisor
|
||
|
to get or set a certain aspect of the SEV virtual machine. The ioctls belong
|
||
|
to the following classes:
|
||
|
|
||
|
- Hypervisor ioctls: These query and set global attributes which affect the
|
||
|
whole SEV firmware. These ioctl are used by platform provisioning tools.
|
||
|
|
||
|
- Guest ioctls: These query and set attributes of the SEV virtual machine.
|
||
|
|
||
|
2. API description
|
||
|
==================
|
||
|
|
||
|
This section describes ioctls that is used for querying the SEV guest report
|
||
|
from the SEV firmware. For each ioctl, the following information is provided
|
||
|
along with a description:
|
||
|
|
||
|
Technology:
|
||
|
which SEV technology provides this ioctl. SEV, SEV-ES, SEV-SNP or all.
|
||
|
|
||
|
Type:
|
||
|
hypervisor or guest. The ioctl can be used inside the guest or the
|
||
|
hypervisor.
|
||
|
|
||
|
Parameters:
|
||
|
what parameters are accepted by the ioctl.
|
||
|
|
||
|
Returns:
|
||
|
the return value. General error numbers (-ENOMEM, -EINVAL)
|
||
|
are not detailed, but errors with specific meanings are.
|
||
|
|
||
|
The guest ioctl should be issued on a file descriptor of the /dev/sev-guest
|
||
|
device. The ioctl accepts struct snp_user_guest_request. The input and
|
||
|
output structure is specified through the req_data and resp_data field
|
||
|
respectively. If the ioctl fails to execute due to a firmware error, then
|
||
|
the fw_error code will be set, otherwise fw_error will be set to -1.
|
||
|
|
||
|
The firmware checks that the message sequence counter is one greater than
|
||
|
the guests message sequence counter. If guest driver fails to increment message
|
||
|
counter (e.g. counter overflow), then -EIO will be returned.
|
||
|
|
||
|
::
|
||
|
|
||
|
struct snp_guest_request_ioctl {
|
||
|
/* Message version number */
|
||
|
__u32 msg_version;
|
||
|
|
||
|
/* Request and response structure address */
|
||
|
__u64 req_data;
|
||
|
__u64 resp_data;
|
||
|
|
||
|
/* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */
|
||
|
union {
|
||
|
__u64 exitinfo2;
|
||
|
struct {
|
||
|
__u32 fw_error;
|
||
|
__u32 vmm_error;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
The host ioctls are issued to a file descriptor of the /dev/sev device.
|
||
|
The ioctl accepts the command ID/input structure documented below.
|
||
|
|
||
|
::
|
||
|
|
||
|
struct sev_issue_cmd {
|
||
|
/* Command ID */
|
||
|
__u32 cmd;
|
||
|
|
||
|
/* Command request structure */
|
||
|
__u64 data;
|
||
|
|
||
|
/* Firmware error code on failure (see psp-sev.h) */
|
||
|
__u32 error;
|
||
|
};
|
||
|
|
||
|
|
||
|
2.1 SNP_GET_REPORT
|
||
|
------------------
|
||
|
|
||
|
:Technology: sev-snp
|
||
|
:Type: guest ioctl
|
||
|
:Parameters (in): struct snp_report_req
|
||
|
:Returns (out): struct snp_report_resp on success, -negative on error
|
||
|
|
||
|
The SNP_GET_REPORT ioctl can be used to query the attestation report from the
|
||
|
SEV-SNP firmware. The ioctl uses the SNP_GUEST_REQUEST (MSG_REPORT_REQ) command
|
||
|
provided by the SEV-SNP firmware to query the attestation report.
|
||
|
|
||
|
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.
|
||
|
|
||
|
|
||
|
2.3 SNP_GET_EXT_REPORT
|
||
|
----------------------
|
||
|
:Technology: sev-snp
|
||
|
:Type: guest ioctl
|
||
|
:Parameters (in/out): struct snp_ext_report_req
|
||
|
:Returns (out): struct snp_report_resp on success, -negative on error
|
||
|
|
||
|
The SNP_GET_EXT_REPORT ioctl is similar to the SNP_GET_REPORT. The difference is
|
||
|
related to the additional certificate data that is returned with the report.
|
||
|
The certificate data returned is being provided by the hypervisor through the
|
||
|
SNP_SET_EXT_CONFIG.
|
||
|
|
||
|
The ioctl uses the SNP_GUEST_REQUEST (MSG_REPORT_REQ) command provided by the SEV-SNP
|
||
|
firmware to get the attestation report.
|
||
|
|
||
|
On success, the snp_ext_report_resp.data will contain the attestation report
|
||
|
and snp_ext_report_req.certs_address will contain the certificate blob. If the
|
||
|
length of the blob is smaller than expected then snp_ext_report_req.certs_len will
|
||
|
be updated with the expected value.
|
||
|
|
||
|
See GHCB specification for further detail on how to parse the certificate blob.
|
||
|
|
||
|
2.4 SNP_PLATFORM_STATUS
|
||
|
-----------------------
|
||
|
:Technology: sev-snp
|
||
|
:Type: hypervisor ioctl cmd
|
||
|
:Parameters (out): struct sev_user_data_snp_status
|
||
|
:Returns (out): 0 on success, -negative on error
|
||
|
|
||
|
The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The
|
||
|
status includes API major, minor version and more. See the SEV-SNP
|
||
|
specification for further details.
|
||
|
|
||
|
2.5 SNP_COMMIT
|
||
|
--------------
|
||
|
:Technology: sev-snp
|
||
|
:Type: hypervisor ioctl cmd
|
||
|
:Returns (out): 0 on success, -negative on error
|
||
|
|
||
|
SNP_COMMIT is used to commit the currently installed firmware using the
|
||
|
SEV-SNP firmware SNP_COMMIT command. This prevents roll-back to a previously
|
||
|
committed firmware version. This will also update the reported TCB to match
|
||
|
that of the currently installed firmware.
|
||
|
|
||
|
2.6 SNP_SET_CONFIG
|
||
|
------------------
|
||
|
:Technology: sev-snp
|
||
|
:Type: hypervisor ioctl cmd
|
||
|
:Parameters (in): struct sev_user_data_snp_config
|
||
|
:Returns (out): 0 on success, -negative on error
|
||
|
|
||
|
SNP_SET_CONFIG is used to set the system-wide configuration such as
|
||
|
reported TCB version in the attestation report. The command is similar
|
||
|
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
|
||
|
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
|
||
|
============================
|
||
|
|
||
|
SEV-SNP guests can access a special page that contains a table of CPUID values
|
||
|
that have been validated by the PSP as part of the SNP_LAUNCH_UPDATE firmware
|
||
|
command. It provides the following assurances regarding the validity of CPUID
|
||
|
values:
|
||
|
|
||
|
- Its address is obtained via bootloader/firmware (via CC blob), and those
|
||
|
binaries will be measured as part of the SEV-SNP attestation report.
|
||
|
- Its initial state will be encrypted/pvalidated, so attempts to modify
|
||
|
it during run-time will result in garbage being written, or #VC exceptions
|
||
|
being generated due to changes in validation state if the hypervisor tries
|
||
|
to swap the backing page.
|
||
|
- Attempts to bypass PSP checks by the hypervisor by using a normal page, or
|
||
|
a non-CPUID encrypted page will change the measurement provided by the
|
||
|
SEV-SNP attestation report.
|
||
|
- The CPUID page contents are *not* measured, but attempts to modify the
|
||
|
expected contents of a CPUID page as part of guest initialization will be
|
||
|
gated by the PSP CPUID enforcement policy checks performed on the page
|
||
|
during SNP_LAUNCH_UPDATE, and noticeable later if the guest owner
|
||
|
implements their own checks of the CPUID values.
|
||
|
|
||
|
It is important to note that this last assurance is only useful if the kernel
|
||
|
has taken care to make use of the SEV-SNP CPUID throughout all stages of boot.
|
||
|
Otherwise, guest owner attestation provides no assurance that the kernel wasn't
|
||
|
fed incorrect values at some point during boot.
|
||
|
|
||
|
4. SEV Guest Driver Communication Key
|
||
|
=====================================
|
||
|
|
||
|
Communication between an SEV guest and the SEV firmware in the AMD Secure
|
||
|
Processor (ASP, aka PSP) is protected by a VM Platform Communication Key
|
||
|
(VMPCK). By default, the sev-guest driver uses the VMPCK associated with the
|
||
|
VM Privilege Level (VMPL) at which the guest is running. Should this key be
|
||
|
wiped by the sev-guest driver (see the driver for reasons why a VMPCK can be
|
||
|
wiped), a different key can be used by reloading the sev-guest driver and
|
||
|
specifying the desired key using the vmpck_id module parameter.
|
||
|
|
||
|
|
||
|
Reference
|
||
|
---------
|
||
|
|
||
|
SEV-SNP and GHCB specification: developer.amd.com/sev
|
||
|
|
||
|
The driver is based on SEV-SNP firmware spec 0.9 and GHCB spec version 2.0.
|