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);