Skip to main content

tss_esapi/error/
return_code.rs

1// Copyright 2022 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3
4mod base;
5mod esapi;
6mod fapi;
7mod muapi;
8mod sapi;
9mod tcti;
10mod tpm;
11
12use crate::{
13    constants::{return_code::ReturnCodeLayer, tss::TSS2_RC_SUCCESS},
14    tss2_esys::TSS2_RC,
15    Error, Result,
16};
17pub use base::BaseReturnCode;
18use bitfield::bitfield;
19pub use esapi::EsapiReturnCode;
20pub use fapi::FapiReturnCode;
21pub use muapi::MuapiReturnCode;
22pub use sapi::SapiReturnCode;
23use std::convert::TryFrom;
24pub use tcti::TctiReturnCode;
25pub use tpm::{
26    ArgumentNumber, TpmFormatOneResponseCode, TpmFormatZeroErrorResponseCode,
27    TpmFormatZeroResponseCode, TpmFormatZeroWarningResponseCode, TpmResponseCode,
28};
29
30/// Enum representing return codes and response codes
31/// from the TSS and the TPM that indicates an error.
32#[derive(Debug, Copy, Clone, PartialEq, Eq)]
33pub enum ReturnCode {
34    Tpm(TpmResponseCode),
35    Fapi(FapiReturnCode),
36    Esapi(EsapiReturnCode),
37    Sapi(SapiReturnCode),
38    Mu(MuapiReturnCode),
39    Tcti(TctiReturnCode),
40    ResourceManager(BaseReturnCode),
41    TpmResourceManager(TpmResponseCode),
42}
43
44impl ReturnCode {
45    /// Ensures that the return code indicates success.
46    ///
47    /// # Arguments
48    /// * `tss2_rc` - A TSS return code value.
49    /// * `f` - Function that will be executed before an error is returned.
50    ///
51    /// # Errors
52    /// Generates the error indicated by the return code.
53    pub(crate) fn ensure_success<F>(tss2_rc: TSS2_RC, f: F) -> Result<()>
54    where
55        F: FnOnce(TSS2_RC),
56    {
57        if ReturnCodeStructure(tss2_rc).is_success() {
58            Ok(())
59        } else {
60            f(tss2_rc);
61            Err(Error::tss_error(ReturnCode::try_from(tss2_rc)?))
62        }
63    }
64}
65
66impl TryFrom<TSS2_RC> for ReturnCode {
67    type Error = Error;
68    fn try_from(tss2_rc: TSS2_RC) -> Result<Self> {
69        let structure = ReturnCodeStructure(tss2_rc);
70        match structure.return_code_layer()? {
71            ReturnCodeLayer::Tpm => {
72                TpmResponseCode::try_from(structure.return_code_data()).map(ReturnCode::Tpm)
73            }
74            ReturnCodeLayer::Feature => {
75                FapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Fapi)
76            }
77            ReturnCodeLayer::Esys => {
78                EsapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Esapi)
79            }
80            ReturnCodeLayer::Sys => {
81                SapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Sapi)
82            }
83            ReturnCodeLayer::Mu => {
84                MuapiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Mu)
85            }
86            ReturnCodeLayer::Tcti => {
87                TctiReturnCode::try_from(structure.return_code_data()).map(ReturnCode::Tcti)
88            }
89            ReturnCodeLayer::ResMgr => BaseReturnCode::try_from(structure.return_code_data())
90                .map(ReturnCode::ResourceManager),
91            ReturnCodeLayer::ResMgrTpm => TpmResponseCode::try_from(structure.return_code_data())
92                .map(ReturnCode::TpmResourceManager),
93        }
94    }
95}
96
97impl From<ReturnCode> for TSS2_RC {
98    fn from(return_code: ReturnCode) -> Self {
99        let mut return_code_structure = ReturnCodeStructure(0);
100        match return_code {
101            ReturnCode::Tpm(rc) => {
102                return_code_structure.set_layer_data(ReturnCodeLayer::Tpm.into());
103                return_code_structure.set_return_code_data(rc.into());
104            }
105            ReturnCode::Fapi(rc) => {
106                return_code_structure.set_layer_data(ReturnCodeLayer::Feature.into());
107                return_code_structure.set_return_code_data(rc.into());
108            }
109            ReturnCode::Esapi(rc) => {
110                return_code_structure.set_layer_data(ReturnCodeLayer::Esys.into());
111                return_code_structure.set_return_code_data(rc.into());
112            }
113            ReturnCode::Sapi(rc) => {
114                return_code_structure.set_layer_data(ReturnCodeLayer::Sys.into());
115                return_code_structure.set_return_code_data(rc.into());
116            }
117            ReturnCode::Mu(rc) => {
118                return_code_structure.set_layer_data(ReturnCodeLayer::Mu.into());
119                return_code_structure.set_return_code_data(rc.into());
120            }
121            ReturnCode::Tcti(rc) => {
122                return_code_structure.set_layer_data(ReturnCodeLayer::Tcti.into());
123                return_code_structure.set_return_code_data(rc.into());
124            }
125            ReturnCode::ResourceManager(rc) => {
126                return_code_structure.set_layer_data(ReturnCodeLayer::ResMgr.into());
127                return_code_structure.set_return_code_data(rc.into());
128            }
129            ReturnCode::TpmResourceManager(rc) => {
130                return_code_structure.set_layer_data(ReturnCodeLayer::ResMgrTpm.into());
131                return_code_structure.set_return_code_data(rc.into());
132            }
133        }
134        return_code_structure.0
135    }
136}
137
138impl std::error::Error for ReturnCode {
139    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
140        match self {
141            ReturnCode::Tpm(rc) => Some(rc),
142            ReturnCode::Fapi(rc) => Some(rc),
143            ReturnCode::Esapi(rc) => Some(rc),
144            ReturnCode::Sapi(rc) => Some(rc),
145            ReturnCode::Mu(rc) => Some(rc),
146            ReturnCode::Tcti(rc) => Some(rc),
147            ReturnCode::ResourceManager(rc) => Some(rc),
148            ReturnCode::TpmResourceManager(rc) => Some(rc),
149        }
150    }
151}
152
153impl std::fmt::Display for ReturnCode {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        match self {
156            ReturnCode::Tpm(e) => write!(
157                f,
158                "TSS Layer: TPM, Code: 0x{:08X}, Message: {}",
159                TSS2_RC::from(*self),
160                e
161            ),
162            ReturnCode::Fapi(e) => write!(
163                f,
164                "TSS Layer: FAPI, Code: 0x{:08X}, Message: {}",
165                TSS2_RC::from(*self),
166                e
167            ),
168            ReturnCode::Esapi(e) => write!(
169                f,
170                "TSS Layer: ESAPI, Code: 0x{:08X}, Message: {}",
171                TSS2_RC::from(*self),
172                e
173            ),
174            ReturnCode::Sapi(e) => write!(
175                f,
176                "TSS Layer: SAPI, Code: 0x{:08X}, Message: {}",
177                TSS2_RC::from(*self),
178                e
179            ),
180            ReturnCode::Mu(e) => write!(
181                f,
182                "TSS Layer: MUAPI, Code: 0x{:08X}, Message: {}",
183                TSS2_RC::from(*self),
184                e
185            ),
186            ReturnCode::Tcti(e) => write!(
187                f,
188                "TSS Layer: TCTI, Code: 0x{:08X}, Message: {}",
189                TSS2_RC::from(*self),
190                e
191            ),
192            ReturnCode::ResourceManager(e) => write!(
193                f,
194                "TSS Layer: RESOURCE MANAGER, Code: 0x{:08X}, Message: {}",
195                TSS2_RC::from(*self),
196                e
197            ),
198            ReturnCode::TpmResourceManager(e) => {
199                write!(
200                    f,
201                    "TSS Layer: TPM RESOURCE MANAGER, Code: 0x{:08X}, Message: {}",
202                    TSS2_RC::from(*self),
203                    e
204                )
205            }
206        }
207    }
208}
209
210bitfield! {
211    /// A structure used for handling a TSS2_RC.
212    #[derive(PartialEq, Copy, Clone)]
213    struct ReturnCodeStructure(TSS2_RC);
214    impl Debug;
215    u8, layer_data, set_layer_data: 23, 16;
216    u16, return_code_data, set_return_code_data: 15, 0;
217}
218
219impl ReturnCodeStructure {
220    /// Returns the layer of the return code.
221    ///
222    /// # Errors
223    /// If the TssReturnCodeStructure does not contain a
224    /// valid layer then an error is returned.
225    fn return_code_layer(&self) -> Result<ReturnCodeLayer> {
226        ReturnCodeLayer::try_from(self.layer_data())
227    }
228
229    /// Checks if the return code indicates success.
230    const fn is_success(&self) -> bool {
231        self.0 == TSS2_RC_SUCCESS
232    }
233}