sev_guest_device/
protocol.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! The module includes the definitions of data structures according to SEV-SNP specification.
5
6use bitfield_struct::bitfield;
7use zerocopy::FromBytes;
8use zerocopy::FromZeros;
9use zerocopy::Immutable;
10use zerocopy::IntoBytes;
11use zerocopy::KnownLayout;
12
13/// Ioctl type defined by Linux.
14pub const SNP_GUEST_REQ_IOC_TYPE: u8 = b'S';
15
16/// Value for the `msg_version` member in [`SNP_GUEST_REQ_MSG_VERSION`].
17/// Use 1 for now.
18pub const SNP_GUEST_REQ_MSG_VERSION: u32 = 1;
19
20/// Ioctl struct defined by Linux.
21#[repr(C)]
22pub struct SnpGuestRequestIoctl {
23    /// Message version number (must be non-zero).
24    pub msg_version: u32,
25    /// Request struct address.
26    pub req_data: u64,
27    /// Response struct address.
28    pub resp_data: u64,
29    /// VMM error code.
30    pub exitinfo: VmmErrorCode,
31}
32
33/// VMM error code.
34#[repr(C)]
35#[derive(FromZeros, Immutable, KnownLayout)]
36pub struct VmmErrorCode {
37    /// Firmware error
38    pub fw_error: u32,
39    /// VMM error
40    pub vmm_error: u32,
41}
42
43/// Request structure for the `SNP_GET_REPORT` ioctl.
44/// See `MSG_REPORT_REQ` in Table 21, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
45#[repr(C)]
46#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
47pub struct SnpReportReq {
48    /// Guest-provided data to be included in the attestation report.
49    pub user_data: [u8; 64],
50    /// The VMPL to put in the attestation report. Must be greater than
51    /// or equal to the current VMPL and, at most, three.
52    pub vmpl: u32,
53    /// Reserved
54    // TODO SNP: Support VLEK feature if needed
55    pub rsvd: [u8; 28],
56}
57
58const SNP_REPORT_RESP_DATA_SIZE: usize =
59    size_of::<u32>() + size_of::<u32>() + 24 + size_of::<SnpReport>();
60
61/// The size of the response data defined by the Linux kernel.
62const LINUX_SNP_REPORT_RESP_DATA_SIZE: usize = 4000;
63
64/// Response structure for the `SNP_GET_REPORT` ioctl.
65/// See `MSG_REPORT_RSP` in Table 24, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
66#[repr(C)]
67#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
68pub struct SnpReportResp {
69    /// The status of key derivation operation.
70    /// 0h: Success.
71    /// 16h: Invalid parameters.
72    /// 27h: Invalid key selection.
73    pub status: u32,
74    /// Size in bytes of the report.
75    pub report_size: u32,
76    /// Reserved
77    pub _reserved0: [u8; 24],
78    /// The attestation report generated by the firmware.
79    pub report: SnpReport,
80    /// Reserved
81    pub _reserved1: [u8; LINUX_SNP_REPORT_RESP_DATA_SIZE - SNP_REPORT_RESP_DATA_SIZE],
82}
83
84static_assertions::const_assert_eq!(LINUX_SNP_REPORT_RESP_DATA_SIZE, size_of::<SnpReportResp>());
85
86/// Size of the [`SnpReport`].
87pub const SNP_REPORT_SIZE: usize = 0x4a0;
88
89/// Size of `report_data` member in [`SnpReport`].
90pub const SNP_REPORT_DATA_SIZE: usize = 64;
91
92/// Report structure.
93/// See `ATTESTATION_REPORT` in Table 22, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
94#[repr(C)]
95#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
96pub struct SnpReport {
97    /// Version number of this attestation report.
98    /// Set to 2h for this specification.
99    pub version: u32,
100    /// The guest SVN.
101    pub guest_svn: u32,
102    /// The guest policy.
103    pub policy: u64,
104    /// The family ID provided at launch.
105    pub family: u128,
106    /// The image ID provided at launch.
107    pub image_id: u128,
108    /// The request VMPL for the attestation
109    /// report.
110    pub vmpl: u32,
111    /// The signature algorithm used to sign
112    /// this report.
113    pub signature_algo: u32,
114    /// CurrentTcb.
115    pub current_tcb: u64,
116    /// Information about the platform.
117    pub platform_info: u64,
118    /// Flags
119    pub flags: u32,
120    /// Reserved
121    pub _reserved0: u32,
122    /// Guest-provided data.
123    pub report_data: [u8; SNP_REPORT_DATA_SIZE],
124    /// The measurement calculated at
125    /// launch.
126    pub measurement: [u8; 48],
127    /// Data provided by the hypervisor at
128    /// launch.
129    pub host_data: [u8; 32],
130    /// SHA-384 digest of the ID public key
131    /// that signed the ID block provided in
132    /// SNP_LAUNCH_FINISH.
133    pub id_key_digest: [u8; 48],
134    /// SHA-384 digest of the Author public
135    /// key that certified the ID key, if
136    /// provided in SNP_LAUNCH_FINISH.
137    pub author_key_digest: [u8; 48],
138    /// Report ID of this guest.
139    pub report_id: [u8; 32],
140    /// Report ID of this guest’s migration
141    /// agent
142    pub report_id_ma: [u8; 32],
143    /// Reported TCB version used to derive
144    /// the VCEK that signed this report.
145    pub reported_tcb: u64,
146    /// Reserved
147    pub _reserved1: [u8; 24],
148    /// If MaskChipId is set to 0, Identifier
149    /// unique to the chip as output by
150    /// GET_ID. Otherwise, set to 0h.
151    pub chip_id: [u8; 64],
152    /// CommittedTcb.
153    pub committed_tcb: u64,
154    /// The build number of CurrentVersion.
155    pub current_build: u8,
156    /// The minor number of CurrentVersion.
157    pub current_minor: u8,
158    /// The major number of CurrentVersion.
159    pub current_major: u8,
160    /// Reserved
161    pub _reserved2: u8,
162    /// The build number of CommittedVersion.
163    pub committed_build: u8,
164    /// The minor version of CommittedVersion.
165    pub committed_minor: u8,
166    /// The major version of CommittedVersion.
167    pub committed_major: u8,
168    /// Reserved
169    pub _reserved3: u8,
170    /// The CurrentTcb at the time the guest
171    /// was launched or imported.
172    pub launch_tcb: u64,
173    /// Reserved
174    pub _reserved4: [u8; 168],
175    /// Signature of bytes inclusive of this report.
176    pub signature: [u8; 512],
177}
178
179static_assertions::const_assert_eq!(SNP_REPORT_SIZE, size_of::<SnpReport>());
180
181/// Request structure for the `SNP_GET_DERIVED_KEY` ioctl.
182/// See `MSG_KEY_REQ` in Table 18, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
183#[repr(C)]
184#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
185pub struct SnpDerivedKeyReq {
186    /// Selects the root key from which to derive the key.
187    /// 0 indicates VCEK
188    /// 1 indicates VMRK
189    // TODO: Support VLEK feature if needed
190    pub root_key_select: u32,
191    /// Reserved
192    pub rsvd: u32,
193    /// Bitmask indicating which data will be mixed into the
194    /// derived key.
195    pub guest_field_select: u64,
196    /// The VMPL to mix into the derived key. Must be greater
197    /// than or equal to the current VMPL.
198    pub vmpl: u32,
199    /// The guest SVN to mix into the key. Must not exceed the
200    /// guest SVN provided at launch in the ID block.
201    pub guest_svn: u32,
202    /// The TCB version to mix into the derived key. Must not
203    /// exceed CommittedTcb.
204    pub tcb_version: u64,
205}
206
207/// Indicate which guest-selectable fields will be mixed into the key.
208/// See `GUEST_FIELD_SELECT` in Table 19, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
209#[bitfield(u64)]
210pub struct GuestFieldSelect {
211    /// Indicate that the guest policy will be mixed into the key.
212    pub guest_policy: bool,
213    /// Indicate that the image ID of the guest will be mixed into the key.
214    pub image_id: bool,
215    /// Indicate the family ID of the guest will be mixed into the key.
216    pub family_id: bool,
217    /// Indicate the measurement of the guest during launch will be mixed into the key.
218    pub measurement: bool,
219    /// Indicate that the guest-provided SVN will be mixed into the key.
220    pub guest_svn: bool,
221    /// Indicate that the guest-provided TCB_VERSION will be mixed into the key.
222    pub tcb_version: bool,
223    /// Reserved
224    #[bits(58)]
225    pub _reserved: u64,
226}
227
228/// See `DERIVED_KEY` in Table 20, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
229pub const SNP_DERIVED_KEY_SIZE: usize = 32;
230
231/// Response structure for the `SNP_GET_DERIVED_KEY` ioctl.
232/// See `MSG_KEY_RSP` in Table 20, "SEV Secure Nested Paging Firmware ABI specification", Revision 1.55.
233#[repr(C)]
234#[derive(IntoBytes, Immutable, KnownLayout, FromBytes)]
235pub struct SnpDerivedKeyResp {
236    /// The status of key derivation operation.
237    /// 0h: Success.
238    /// 16h: Invalid parameters.
239    /// 27h: Invalid key selection.
240    pub status: u32,
241    /// Reserved
242    pub _reserved: [u8; 28],
243    /// The requested derived key.
244    pub derived_key: [u8; SNP_DERIVED_KEY_SIZE],
245}
246
247static_assertions::const_assert_eq!(
248    // The size of the response data defined by the Linux kernel.
249    64,
250    size_of::<SnpDerivedKeyResp>()
251);