最终 SEV 访客 API 文档¶
1. 概述¶
SEV API 是一组 ioctl,访客或虚拟机监控程序使用它们来获取或设置 SEV 虚拟机 的某些方面。 ioctl 属于以下类别
虚拟机监控程序 ioctl: 这些查询和设置影响整个 SEV 固件的全局属性。 这些 ioctl 由平台配置工具使用。
访客 ioctl: 这些查询和设置 SEV 虚拟机的属性。
2. API 描述¶
本节描述用于从 SEV 固件查询 SEV 访客报告的 ioctl。 对于每个 ioctl,将提供以下信息以及描述
- 技术
哪个 SEV 技术提供此 ioctl。 SEV、SEV-ES、SEV-SNP 或全部。
- 类型
虚拟机监控程序或访客。 ioctl 可以在访客或虚拟机监控程序内部使用。
- 参数
ioctl 接受哪些参数。
- 返回值
返回值。 不会详细说明一般的错误号(-ENOMEM、-EINVAL),但会说明具有特定含义的错误。
应在 /dev/sev-guest 设备的 文件描述符上发出访客 ioctl。 ioctl 接受 struct snp_user_guest_request。 输入和输出结构分别通过 req_data 和 resp_data 字段指定。 如果 ioctl 由于固件错误而执行失败,则 fw_error 代码将被设置,否则 fw_error 将被设置为 -1。
固件检查消息序列计数器是否比访客消息序列计数器大一。 如果访客驱动程序未能递增消息计数器(例如,计数器溢出),则将返回 -EIO。
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;
};
};
};
主机 ioctl 将发送到 /dev/sev 设备的 文件描述符。 ioctl 接受以下记录的命令 ID/输入结构。
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¶
- 技术:
sev-snp
- 类型:
访客 ioctl
- 参数(输入):
struct snp_report_req
- 返回值(输出):
成功时为 struct snp_report_resp,错误时为 -负数
SNP_GET_REPORT ioctl 可用于从 SEV-SNP 固件查询认证报告。 ioctl 使用 SEV-SNP 固件提供的 SNP_GUEST_REQUEST (MSG_REPORT_REQ) 命令来查询认证报告。
成功时,snp_report_resp.data 将包含报告。 报告包含 SEV-SNP 规范中描述的格式。 有关更多详细信息,请参阅 SEV-SNP 规范。
2.2 SNP_GET_DERIVED_KEY¶
- 技术:
sev-snp
- 类型:
访客 ioctl
- 参数(输入):
struct snp_derived_key_req
- 返回值(输出):
成功时为 struct snp_derived_key_resp,错误时为 -负数
SNP_GET_DERIVED_KEY ioctl 可用于获取从根密钥派生的密钥。 派生的密钥可供访客用于任何目的,例如密封密钥或与外部实体通信。
ioctl 使用 SEV-SNP 固件提供的 SNP_GUEST_REQUEST (MSG_KEY_REQ) 命令来派生密钥。 有关密钥派生请求中传递的各种字段的更多详细信息,请参阅 SEV-SNP 规范。
成功时,snp_derived_key_resp.data 包含派生的密钥值。 有关更多详细信息,请参阅 SEV-SNP 规范。
2.3 SNP_GET_EXT_REPORT¶
- 技术:
sev-snp
- 类型:
访客 ioctl
- 参数(输入/输出):
struct snp_ext_report_req
- 返回值(输出):
成功时为 struct snp_report_resp,错误时为 -负数
SNP_GET_EXT_REPORT ioctl 与 SNP_GET_REPORT 类似。 不同之处在于与报告一起返回的额外证书数据。 返回的证书数据由虚拟机监控程序通过 SNP_SET_EXT_CONFIG 提供。
ioctl 使用 SEV-SNP 固件提供的 SNP_GUEST_REQUEST (MSG_REPORT_REQ) 命令来获取认证报告。
成功时,snp_ext_report_resp.data 将包含认证报告,snp_ext_report_req.certs_address 将包含证书 blob。 如果 blob 的长度小于预期,则将使用预期值更新 snp_ext_report_req.certs_len。
有关如何解析证书 blob 的更多详细信息,请参阅 GHCB 规范。
2.4 SNP_PLATFORM_STATUS¶
- 技术:
sev-snp
- 类型:
虚拟机监控程序 ioctl 命令
- 参数(输出):
struct sev_user_data_snp_status
- 返回值(输出):
成功时为 0,错误时为 -负数
SNP_PLATFORM_STATUS 命令用于查询 SNP 平台状态。 该状态包括 API 主版本号、次版本号等。 有关更多详细信息,请参阅 SEV-SNP 规范。
2.5 SNP_COMMIT¶
- 技术:
sev-snp
- 类型:
虚拟机监控程序 ioctl 命令
- 返回值(输出):
成功时为 0,错误时为 -负数
SNP_COMMIT 用于使用 SEV-SNP 固件 SNP_COMMIT 命令提交当前安装的固件。 这将防止回滚到先前提交的固件版本。 这还将更新报告的 TCB 以匹配当前安装的固件的 TCB。
2.6 SNP_SET_CONFIG¶
- 技术:
sev-snp
- 类型:
虚拟机监控程序 ioctl 命令
- 参数(输入):
struct sev_user_data_snp_config
- 返回值(输出):
成功时为 0,错误时为 -负数
SNP_SET_CONFIG 用于设置系统范围的配置,例如认证报告中报告的 TCB 版本。 该命令类似于 SEV-SNP 规范中定义的 SNP_CONFIG 命令。 可以通过 SNP_PLATFORM_STATUS 查询受此命令影响的固件参数的当前值。
2.7 SNP_VLEK_LOAD¶
- 技术:
sev-snp
- 类型:
虚拟机监控程序 ioctl 命令
- 参数(输入):
struct sev_user_data_snp_vlek_load
- 返回值(输出):
成功时为 0,错误时为 -负数
在请求认证报告时,访客可以指定它是否希望 SNP 固件使用版本化芯片背书密钥 (VCEK) 对报告进行签名,该密钥是从芯片唯一的秘密派生的,或者使用版本化加载背书密钥 (VLEK),该密钥是从 AMD 密钥派生服务 (KDS) 获得的,并从分配给已注册云服务提供商的种子派生而来。
对于 VLEK 密钥,SNP_VLEK_LOAD SNP 命令用于在从 KDS 获取后将其加载到系统中,并且与 SEV-SNP 规范中指定的 SNP_VLEK_LOAD 固件命令密切对应。
3. SEV-SNP CPUID 强制执行¶
SEV-SNP 访客可以访问一个特殊页面,其中包含由 PSP 作为 SNP_LAUNCH_UPDATE 固件命令的一部分进行验证的 CPUID 值表。 它提供了以下关于 CPUID 值有效性的保证
它的地址是通过引导加载程序/固件(通过 CC blob)获得的,并且这些二进制文件将作为 SEV-SNP 认证报告的一部分进行测量。
它的初始状态将被加密/p 验证,因此在运行时尝试修改它将导致写入垃圾,或者由于虚拟机监控程序尝试交换后备页面时验证状态发生更改而生成 #VC 异常。
虚拟机监控程序尝试通过使用普通页面或非 CPUID 加密页面来绕过 PSP 检查将更改 SEV-SNP 认证报告提供的测量值。
CPUID 页面内容未被测量,但是,在访客初始化过程中,尝试修改 CPUID 页面的预期内容将被 PSP CPUID 强制执行策略检查所控制,这些检查是在 SNP_LAUNCH_UPDATE 期间在页面上执行的,如果访客所有者实现了他们自己的 CPUID 值检查,则稍后会注意到。
重要的是要注意,只有在内核在引导的所有阶段都注意使用 SEV-SNP CPUID 的情况下,最后一个保证才有用。 否则,访客所有者认证不能保证内核在引导的某个时候没有被馈送不正确的值。
4. SEV 访客驱动程序通信密钥¶
SEV 访客与 AMD 安全处理器(ASP,又名 PSP)中的 SEV 固件之间的通信受 VM 平台通信密钥 (VMPCK) 保护。 默认情况下,sev-guest 驱动程序使用与访客运行所在的 VM 特权级别 (VMPL) 关联的 VMPCK。 如果此密钥被 sev-guest 驱动程序擦除(请参阅驱动程序以了解 VMPCK 被擦除的原因),则可以通过重新加载 sev-guest 驱动程序并使用 vmpck_id 模块参数指定所需的密钥来使用不同的密钥。
参考¶
SEV-SNP 和 GHCB 规范:developer.amd.com/sev
该驱动程序基于 SEV-SNP 固件规范 0.9 和 GHCB 规范 2.0 版。