1use openssl::error::ErrorStack;
7use std::{
8 convert::From,
9 error,
10 fmt::{Debug, Display},
11 io,
12};
13
14#[derive(Debug)]
20#[repr(u32)]
21pub enum Error {
22 IoError(io::Error),
25
26 InvalidPlatformState, InvalidGuestState, InvalidConfig, InvalidLen, AlreadyOwned, InvalidCertificate, PolicyFailure, Inactive, InvalidAddress, BadSignature, BadMeasurement, AsidOwned, InvalidAsid, WbinvdRequired, DfFlushRequired, InvalidGuest, InvalidCommand, Active, HardwarePlatform, HardwareUnsafe, Unsupported, InvalidParam, ResourceLimit, SecureDataInvalid, InvalidPageSize, InvalidPageState, InvalidMdataEntry, InvalidPageOwner, AEADOFlow, RbModeExited = 0x001F, RMPInitRequired = 0x0020, BadSvn, BadVersion, ShutdownRequired, UpdateFailed, RestoreRequired, RMPInitFailed, InvalidKey, Custom(String), Unknown, }
151
152#[derive(Debug)]
157pub enum Indeterminate<T: Debug> {
158 Known(T),
160
161 Unknown,
163}
164
165impl std::fmt::Display for Error {
166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 let err_description = match self {
168 Error::IoError(_) => "I/O Error",
169 Error::InvalidPlatformState => "Invalid platform state",
170 Error::InvalidGuestState => "Invalid guest state",
171 Error::InvalidConfig => "Platform configuration invalid",
172 Error::InvalidLen => "Memory buffer too small",
173 Error::AlreadyOwned => "Platform is already owned",
174 Error::InvalidCertificate => "Invalid certificate",
175 Error::PolicyFailure => "Policy failure",
176 Error::Inactive => "Guest is inactive",
177 Error::InvalidAddress => "Provided address is invalid",
178 Error::BadSignature => "Provided signature is invalid",
179 Error::BadMeasurement => "Provided measurement is invalid",
180 Error::AsidOwned => "ASID is already owned",
181 Error::InvalidAsid => "ASID is invalid",
182 Error::WbinvdRequired => "WBINVD instruction required",
183 Error::DfFlushRequired => "DF_FLUSH invocation required",
184 Error::InvalidGuest => "Guest handle is invalid",
185 Error::InvalidCommand => "Issued command is invalid",
186 Error::Active => "Guest is active",
187 Error::HardwarePlatform => {
188 "Hardware condition occured, safe to re-allocate parameter buffers"
189 }
190 Error::HardwareUnsafe => {
191 "Hardware condition occured, unsafe to re-allocate parameter buffers"
192 }
193 Error::Unsupported => "Feature is unsupported",
194 Error::InvalidParam => "Given parameter is invalid",
195 Error::ResourceLimit => {
196 "CSV firmware has run out of required resources to carry out command"
197 }
198 Error::SecureDataInvalid => "CSV platform observed a failed integrity check",
199 Error::InvalidPageSize => "The RMP page size is incorrect.",
200 Error::InvalidPageState => "The RMP page state is incorrect.",
201 Error::InvalidMdataEntry => "The metadata entry is invalid.",
202 Error::InvalidPageOwner => "The page ownership is incorrect",
203 Error::AEADOFlow => "The AEAD algorithm would have overflowed.",
204 Error::RbModeExited => "A Mailbox mode command was sent while the CSV FW was in Ring Buffer \
205 mode. Ring Buffer mode has been exited; the Mailbox mode command has \
206 been ignored. Retry is recommended.",
207 Error::RMPInitRequired => "The RMP must be reinitialized.",
208 Error::BadSvn => "SVN of provided image is lower than the committed SVN",
209 Error::BadVersion => "Firmware version anti-rollback.",
210 Error::ShutdownRequired => "An invocation of SNP_SHUTDOWN is required to complete this action.",
211 Error::UpdateFailed => "Update of the firmware internal state or a guest context page has failed.",
212 Error::RestoreRequired => "Installation of the committed firmware image required.",
213 Error::RMPInitFailed => "The RMP initialization failed.",
214 Error::InvalidKey => "The key requested is invalid, not present, or not allowed",
215 Error::Custom(msg) => msg,
216 Error::Unknown => "Unknown Error",
217 };
218 write!(f, "{err_description}")
219 }
220}
221
222impl error::Error for Error {
223 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
224 match self {
225 Error::IoError(e) => Some(e),
226 _ => None,
227 }
228 }
229}
230
231impl From<io::Error> for Error {
232 #[inline]
233 fn from(error: io::Error) -> Error {
234 Error::IoError(error)
235 }
236}
237
238impl From<ErrorStack> for Error {
239 #[inline]
240 fn from(error: ErrorStack) -> Error {
241 Error::IoError(io::Error::from(error))
242 }
243}
244
245impl error::Error for Indeterminate<Error> {}
246
247impl Display for Indeterminate<Error> {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 let err_description = match self {
250 Indeterminate::Known(error) => format!("Known Error: {error}"),
251 Indeterminate::Unknown => "Unknown Error Encountered".to_string(),
252 };
253
254 write!(f, "{err_description}")
255 }
256}
257
258impl From<io::Error> for Indeterminate<Error> {
259 #[inline]
260 fn from(error: io::Error) -> Indeterminate<Error> {
261 Indeterminate::Known(error.into())
262 }
263}
264
265impl From<u32> for Indeterminate<Error> {
266 #[inline]
267 fn from(error: u32) -> Indeterminate<Error> {
268 Indeterminate::Known(match error {
269 0x00 => io::Error::last_os_error().into(),
270 0x01 => Error::InvalidPlatformState,
271 0x02 => Error::InvalidGuestState,
272 0x03 => Error::InvalidConfig,
273 0x04 => Error::InvalidLen,
274 0x05 => Error::AlreadyOwned,
275 0x06 => Error::InvalidCertificate,
276 0x07 => Error::PolicyFailure,
277 0x08 => Error::Inactive,
278 0x09 => Error::InvalidAddress,
279 0x0A => Error::BadSignature,
280 0x0B => Error::BadMeasurement,
281 0x0C => Error::AsidOwned,
282 0x0D => Error::InvalidAsid,
283 0x0E => Error::WbinvdRequired,
284 0x0F => Error::DfFlushRequired,
285 0x10 => Error::InvalidGuest,
286 0x11 => Error::InvalidCommand,
287 0x12 => Error::Active,
288 0x13 => Error::HardwarePlatform,
289 0x14 => Error::HardwareUnsafe,
290 0x15 => Error::Unsupported,
291 0x16 => Error::InvalidParam,
292 0x17 => Error::ResourceLimit,
293 0x18 => Error::SecureDataInvalid,
294 0x19 => Error::InvalidPageSize,
295 0x1A => Error::InvalidPageState,
296 0x1B => Error::InvalidMdataEntry,
297 0x1C => Error::InvalidPageOwner,
298 0x1D => Error::AEADOFlow,
299 0x1F => Error::RbModeExited,
300 0x20 => Error::RMPInitRequired,
301 0x21 => Error::BadSvn,
302 0x22 => Error::BadVersion,
303 0x23 => Error::ShutdownRequired,
304 0x24 => Error::UpdateFailed,
305 0x25 => Error::RestoreRequired,
306 0x26 => Error::RMPInitFailed,
307 0x27 => Error::InvalidKey,
308 0x28 => Error::Custom(format!("Custom error (code: 0x{:X})", error)),
309 _ => return Indeterminate::Unknown,
310 })
311 }
312}
313
314impl From<Indeterminate<Error>> for io::Error {
315 #[inline]
316 fn from(indeterminate: Indeterminate<Error>) -> io::Error {
317 match indeterminate {
318 Indeterminate::Known(e) => io::Error::new(io::ErrorKind::Other, e),
319 Indeterminate::Unknown => io::Error::new(io::ErrorKind::Other, "unknown CSV error"),
320 }
321 }
322}
323
324impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
325 fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
326 Error::Custom(e.to_string())
327 }
328}