mod base;
mod esapi;
mod fapi;
mod muapi;
mod sapi;
mod tcti;
mod tpm;
use crate::{
constants::{return_code::ReturnCodeLayer, tss::TSS2_RC_SUCCESS},
tss2_esys::TSS2_RC,
Error, Result,
};
pub use base::BaseReturnCode;
use bitfield::bitfield;
pub use esapi::EsapiReturnCode;
pub use fapi::FapiReturnCode;
pub use muapi::MuapiReturnCode;
pub use sapi::SapiReturnCode;
use std::convert::TryFrom;
pub use tcti::TctiReturnCode;
pub use tpm::{
ArgumentNumber, TpmFormatOneResponseCode, TpmFormatZeroErrorResponseCode,
TpmFormatZeroResponseCode, TpmFormatZeroWarningResponseCode, TpmResponseCode,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ReturnCode {
Tpm(TpmResponseCode),
Fapi(FapiReturnCode),
Esapi(EsapiReturnCode),
Sapi(SapiReturnCode),
Mu(MuapiReturnCode),
Tcti(TctiReturnCode),
ResourceManager(BaseReturnCode),
TpmResourceManager(TpmResponseCode),
}
impl ReturnCode {
pub(crate) fn ensure_success<F>(tss2_rc: TSS2_RC, f: F) -> Result<()>
where
F: FnOnce(TSS2_RC),
{
if ReturnCodeStructure(tss2_rc).is_success() {
Ok(())
} else {
f(tss2_rc);
Err(Error::tss_error(ReturnCode::try_from(tss2_rc)?))
}
}
}
impl TryFrom<TSS2_RC> for ReturnCode {
type Error = Error;
fn try_from(tss2_rc: TSS2_RC) -> Result<Self> {
let structure = ReturnCodeStructure(tss2_rc);
match structure.return_code_layer()? {
ReturnCodeLayer::Tpm => {
TpmResponseCode::try_from(structure.return_code_data()).map(ReturnCode::Tpm)
}
ReturnCodeLayer::Feature => {
FapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Fapi)
}
ReturnCodeLayer::Esys => {
EsapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Esapi)
}
ReturnCodeLayer::Sys => {
SapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Sapi)
}
ReturnCodeLayer::Mu => {
MuapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Mu)
}
ReturnCodeLayer::Tcti => {
TctiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Tcti)
}
ReturnCodeLayer::ResMgr => BaseReturnCode::try_from(structure.return_code_data())
.map(ReturnCode::ResourceManager),
ReturnCodeLayer::ResMgrTpm => TpmResponseCode::try_from(structure.return_code_data())
.map(ReturnCode::TpmResourceManager),
}
}
}
impl From<ReturnCode> for TSS2_RC {
fn from(return_code: ReturnCode) -> Self {
let mut return_code_structure = ReturnCodeStructure(0);
match return_code {
ReturnCode::Tpm(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Tpm.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::Fapi(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Feature.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::Esapi(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Esys.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::Sapi(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Sys.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::Mu(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Mu.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::Tcti(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::Tcti.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::ResourceManager(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::ResMgr.into());
return_code_structure.set_return_code_data(rc.into());
}
ReturnCode::TpmResourceManager(rc) => {
return_code_structure.set_layer_data(ReturnCodeLayer::ResMgrTpm.into());
return_code_structure.set_return_code_data(rc.into());
}
}
return_code_structure.0
}
}
impl std::error::Error for ReturnCode {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
ReturnCode::Tpm(rc) => Some(rc),
ReturnCode::Fapi(rc) => Some(rc),
ReturnCode::Esapi(rc) => Some(rc),
ReturnCode::Sapi(rc) => Some(rc),
ReturnCode::Mu(rc) => Some(rc),
ReturnCode::Tcti(rc) => Some(rc),
ReturnCode::ResourceManager(rc) => Some(rc),
ReturnCode::TpmResourceManager(rc) => Some(rc),
}
}
}
impl std::fmt::Display for ReturnCode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReturnCode::Tpm(e) => write!(
f,
"TSS Layer: TPM, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::Fapi(e) => write!(
f,
"TSS Layer: FAPI, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::Esapi(e) => write!(
f,
"TSS Layer: ESAPI, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::Sapi(e) => write!(
f,
"TSS Layer: SAPI, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::Mu(e) => write!(
f,
"TSS Layer: MUAPI, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::Tcti(e) => write!(
f,
"TSS Layer: TCTI, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::ResourceManager(e) => write!(
f,
"TSS Layer: RESOURCE MANAGER, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
),
ReturnCode::TpmResourceManager(e) => {
write!(
f,
"TSS Layer: TPM RESOURCE MANAGER, Code: 0x{:08X}, Message: {}",
TSS2_RC::from(*self),
e
)
}
}
}
}
bitfield! {
#[derive(PartialEq, Copy, Clone)]
struct ReturnCodeStructure(TSS2_RC);
impl Debug;
u8, layer_data, set_layer_data: 23, 16;
u16, return_code_data, set_return_code_data: 15, 0;
}
impl ReturnCodeStructure {
fn return_code_layer(&self) -> Result<ReturnCodeLayer> {
ReturnCodeLayer::try_from(self.layer_data())
}
const fn is_success(&self) -> bool {
self.0 == TSS2_RC_SUCCESS
}
}