use openssl::error::ErrorStack;
use std::{
convert::From,
error,
fmt::{Debug, Display},
io,
};
#[derive(Debug)]
#[repr(u32)]
pub enum Error {
IoError(io::Error),
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, }
#[derive(Debug)]
pub enum Indeterminate<T: Debug> {
Known(T),
Unknown,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let err_description = match self {
Error::IoError(_) => "I/O Error",
Error::InvalidPlatformState => "Invalid platform state",
Error::InvalidGuestState => "Invalid guest state",
Error::InvalidConfig => "Platform configuration invalid",
Error::InvalidLen => "Memory buffer too small",
Error::AlreadyOwned => "Platform is already owned",
Error::InvalidCertificate => "Invalid certificate",
Error::PolicyFailure => "Policy failure",
Error::Inactive => "Guest is inactive",
Error::InvalidAddress => "Provided address is invalid",
Error::BadSignature => "Provided signature is invalid",
Error::BadMeasurement => "Provided measurement is invalid",
Error::AsidOwned => "ASID is already owned",
Error::InvalidAsid => "ASID is invalid",
Error::WbinvdRequired => "WBINVD instruction required",
Error::DfFlushRequired => "DF_FLUSH invocation required",
Error::InvalidGuest => "Guest handle is invalid",
Error::InvalidCommand => "Issued command is invalid",
Error::Active => "Guest is active",
Error::HardwarePlatform => {
"Hardware condition occured, safe to re-allocate parameter buffers"
}
Error::HardwareUnsafe => {
"Hardware condition occured, unsafe to re-allocate parameter buffers"
}
Error::Unsupported => "Feature is unsupported",
Error::InvalidParam => "Given parameter is invalid",
Error::ResourceLimit => {
"CSV firmware has run out of required resources to carry out command"
}
Error::SecureDataInvalid => "CSV platform observed a failed integrity check",
Error::InvalidPageSize => "The RMP page size is incorrect.",
Error::InvalidPageState => "The RMP page state is incorrect.",
Error::InvalidMdataEntry => "The metadata entry is invalid.",
Error::InvalidPageOwner => "The page ownership is incorrect",
Error::AEADOFlow => "The AEAD algorithm would have overflowed.",
Error::RbModeExited => "A Mailbox mode command was sent while the CSV FW was in Ring Buffer \
mode. Ring Buffer mode has been exited; the Mailbox mode command has \
been ignored. Retry is recommended.",
Error::RMPInitRequired => "The RMP must be reinitialized.",
Error::BadSvn => "SVN of provided image is lower than the committed SVN",
Error::BadVersion => "Firmware version anti-rollback.",
Error::ShutdownRequired => "An invocation of SNP_SHUTDOWN is required to complete this action.",
Error::UpdateFailed => "Update of the firmware internal state or a guest context page has failed.",
Error::RestoreRequired => "Installation of the committed firmware image required.",
Error::RMPInitFailed => "The RMP initialization failed.",
Error::InvalidKey => "The key requested is invalid, not present, or not allowed",
Error::Custom(msg) => msg,
Error::Unknown => "Unknown Error",
};
write!(f, "{err_description}")
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Error::IoError(e) => Some(e),
_ => None,
}
}
}
impl From<io::Error> for Error {
#[inline]
fn from(error: io::Error) -> Error {
Error::IoError(error)
}
}
impl From<ErrorStack> for Error {
#[inline]
fn from(error: ErrorStack) -> Error {
Error::IoError(io::Error::from(error))
}
}
impl error::Error for Indeterminate<Error> {}
impl Display for Indeterminate<Error> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let err_description = match self {
Indeterminate::Known(error) => format!("Known Error: {error}"),
Indeterminate::Unknown => "Unknown Error Encountered".to_string(),
};
write!(f, "{err_description}")
}
}
impl From<io::Error> for Indeterminate<Error> {
#[inline]
fn from(error: io::Error) -> Indeterminate<Error> {
Indeterminate::Known(error.into())
}
}
impl From<u32> for Indeterminate<Error> {
#[inline]
fn from(error: u32) -> Indeterminate<Error> {
Indeterminate::Known(match error {
0x00 => io::Error::last_os_error().into(),
0x01 => Error::InvalidPlatformState,
0x02 => Error::InvalidGuestState,
0x03 => Error::InvalidConfig,
0x04 => Error::InvalidLen,
0x05 => Error::AlreadyOwned,
0x06 => Error::InvalidCertificate,
0x07 => Error::PolicyFailure,
0x08 => Error::Inactive,
0x09 => Error::InvalidAddress,
0x0A => Error::BadSignature,
0x0B => Error::BadMeasurement,
0x0C => Error::AsidOwned,
0x0D => Error::InvalidAsid,
0x0E => Error::WbinvdRequired,
0x0F => Error::DfFlushRequired,
0x10 => Error::InvalidGuest,
0x11 => Error::InvalidCommand,
0x12 => Error::Active,
0x13 => Error::HardwarePlatform,
0x14 => Error::HardwareUnsafe,
0x15 => Error::Unsupported,
0x16 => Error::InvalidParam,
0x17 => Error::ResourceLimit,
0x18 => Error::SecureDataInvalid,
0x19 => Error::InvalidPageSize,
0x1A => Error::InvalidPageState,
0x1B => Error::InvalidMdataEntry,
0x1C => Error::InvalidPageOwner,
0x1D => Error::AEADOFlow,
0x1F => Error::RbModeExited,
0x20 => Error::RMPInitRequired,
0x21 => Error::BadSvn,
0x22 => Error::BadVersion,
0x23 => Error::ShutdownRequired,
0x24 => Error::UpdateFailed,
0x25 => Error::RestoreRequired,
0x26 => Error::RMPInitFailed,
0x27 => Error::InvalidKey,
0x28 => Error::Custom(format!("Custom error (code: 0x{:X})", error)),
_ => return Indeterminate::Unknown,
})
}
}
impl From<Indeterminate<Error>> for io::Error {
#[inline]
fn from(indeterminate: Indeterminate<Error>) -> io::Error {
match indeterminate {
Indeterminate::Known(e) => io::Error::new(io::ErrorKind::Other, e),
Indeterminate::Unknown => io::Error::new(io::ErrorKind::Other, "unknown CSV error"),
}
}
}
impl From<Box<dyn std::error::Error + Send + Sync>> for Error {
fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
Error::Custom(e.to_string())
}
}