SEV Guest 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),但具有特定含義的錯誤除外。
訪客 ioctl 應在 /dev/sev-guest 裝置的檔案描述符上發出。 ioctl 接受 struct snp_user_guest_request。 輸入和輸出結構分別透過 req_data 和 resp_data 欄位指定。 如果 ioctl 由於韌體錯誤而執行失敗,則將設定 fw_error 程式碼,否則 fw_error 將設定為 -1。
韌體檢查訊息序列計數器是否比訪客的訊息序列計數器大 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,錯誤時為 -negative
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,錯誤時為 -negative
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,錯誤時為 -negative
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 cmd
- 引數(輸出):
struct sev_user_data_snp_status
- 返回值(輸出):
成功時為 0,錯誤時為 -negative
SNP_PLATFORM_STATUS 命令用於查詢 SNP 平臺狀態。 該狀態包括 API 主要版本、次要版本等。 有關更多詳細資訊,請參閱 SEV-SNP 規範。
2.5 SNP_COMMIT¶
- 技術:
sev-snp
- 型別:
虛擬機器管理程式 ioctl cmd
- 返回值(輸出):
成功時為 0,錯誤時為 -negative
SNP_COMMIT 用於使用 SEV-SNP 韌體 SNP_COMMIT 命令提交當前安裝的韌體。 這樣可以防止回滾到先前提交的韌體版本。 這還將更新報告的 TCB 以匹配當前安裝的韌體的 TCB。
2.6 SNP_SET_CONFIG¶
- 技術:
sev-snp
- 型別:
虛擬機器管理程式 ioctl cmd
- 輸入引數:
struct sev_user_data_snp_config
- 返回值(輸出):
成功時為 0,錯誤時為 -negative
SNP_SET_CONFIG 用於設定系統範圍的配置,例如證明報告中報告的 TCB 版本。 該命令類似於 SEV-SNP 規範中定義的 SNP_CONFIG 命令。 受此命令影響的韌體引數的當前值可以透過 SNP_PLATFORM_STATUS 查詢。
2.7 SNP_VLEK_LOAD¶
- 技術:
sev-snp
- 型別:
虛擬機器管理程式 ioctl cmd
- 輸入引數:
struct sev_user_data_snp_vlek_load
- 返回值(輸出):
成功時為 0,錯誤時為 -negative
在請求證明報告時,訪客可以指定是否希望 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 證明報告的一部分進行度量。
其初始狀態將被加密/pvalidated,因此在執行時嘗試修改它會導致寫入垃圾,或者如果虛擬機器管理程式嘗試交換後備頁面,則由於驗證狀態的更改而生成 #VC 異常。
虛擬機器管理程式嘗試透過使用普通頁面或非 CPUID 加密頁面來繞過 PSP 檢查將更改 SEV-SNP 證明報告提供的度量。
CPUID 頁面內容未被度量,但在訪客初始化過程中嘗試修改 CPUID 頁面的預期內容將受到在 SNP_LAUNCH_UPDATE 期間對頁面執行的 PSP CPUID 強制策略檢查的限制,如果訪客所有者實現了他們自己對 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。