Skip to main content

optee_teec/
error.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::raw;
19use num_enum::{FromPrimitive, IntoPrimitive};
20use std::fmt;
21
22/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
23/// type for TEE operations.
24///
25/// # Examples
26///
27/// ``` no_run
28/// use optee_teec::Context;
29///
30/// fn main() -> optee_teec::Result<()> {
31///     let mut ctx = Context::new()?;
32///     Ok(())
33/// }
34/// ````
35pub type Result<T> = std::result::Result<T, Error>;
36
37/// The error type for TEE operations of [`Context`] and [`Session`].
38///
39/// [`Context`]: struct.Context.html
40/// [`Session`]: struct.Session.html
41#[derive(Clone)]
42pub struct Error {
43    kind: ErrorKind,
44    origin: Option<ErrorOrigin>,
45}
46
47/// A list specifying general categories of TEE client error and its
48/// corresponding code in OP-TEE client library.
49#[derive(
50    Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromPrimitive, IntoPrimitive,
51)]
52#[repr(u32)]
53pub enum ErrorKind {
54    /// Non-specific cause.
55    Generic = raw::TEEC_ERROR_GENERIC,
56    /// Access privileges are not sufficient.
57    AccessDenied = raw::TEEC_ERROR_ACCESS_DENIED,
58    /// The operation was canceled.
59    Cancel = raw::TEEC_ERROR_CANCEL,
60    /// Concurrent accesses caused conflict.
61    AccessConflict = raw::TEEC_ERROR_ACCESS_CONFLICT,
62    /// Too much data for the requested operation was passed.
63    ExcessData = raw::TEEC_ERROR_EXCESS_DATA,
64    /// Input data was of invalid format.
65    BadFormat = raw::TEEC_ERROR_BAD_FORMAT,
66    /// Input parameters were invalid.
67    BadParameters = raw::TEEC_ERROR_BAD_PARAMETERS,
68    /// Operation is not valid in the current state.
69    BadState = raw::TEEC_ERROR_BAD_STATE,
70    /// The requested data item is not found.
71    ItemNotFound = raw::TEEC_ERROR_ITEM_NOT_FOUND,
72    /// The requested operation should exist but is not yet implemented.
73    NotImplemented = raw::TEEC_ERROR_NOT_IMPLEMENTED,
74    /// The requested operation is valid but is not supported in this implementation.
75    NotSupported = raw::TEEC_ERROR_NOT_SUPPORTED,
76    /// Expected data was missing.
77    NoData = raw::TEEC_ERROR_NO_DATA,
78    /// System ran out of resources.
79    OutOfMemory = raw::TEEC_ERROR_OUT_OF_MEMORY,
80    /// The system is busy working on something else.
81    Busy = raw::TEEC_ERROR_BUSY,
82    /// Communication with a remote party failed.
83    Communication = raw::TEEC_ERROR_COMMUNICATION,
84    /// A security fault was detected.
85    Security = raw::TEEC_ERROR_SECURITY,
86    /// The supplied buffer is too short for the generated output.
87    ShortBuffer = raw::TEEC_ERROR_SHORT_BUFFER,
88    /// Implementation defined error code.
89    ExternalCancel = raw::TEEC_ERROR_EXTERNAL_CANCEL,
90    /// Implementation defined error code: trusted Application has panicked during the operation.
91    TargetDead = raw::TEEC_ERROR_TARGET_DEAD,
92    /// Unknown error.
93    #[default]
94    Unknown,
95}
96
97impl ErrorKind {
98    pub(crate) fn as_str(&self) -> &'static str {
99        match self {
100            ErrorKind::Generic => "Non-specific cause.",
101            ErrorKind::AccessDenied => "Access privileges are not sufficient.",
102            ErrorKind::Cancel => "The operation was canceled.",
103            ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
104            ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
105            ErrorKind::BadFormat => "Input data was of invalid format.",
106            ErrorKind::BadParameters => "Input parameters were invalid.",
107            ErrorKind::BadState => "Operation is not valid in the current state.",
108            ErrorKind::ItemNotFound => "The requested data item is not found.",
109            ErrorKind::NotImplemented => {
110                "The requested operation should exist but is not yet implemented."
111            }
112            ErrorKind::NotSupported => {
113                "The requested operation is valid but is not supported in this implementation."
114            }
115            ErrorKind::NoData => "Expected data was missing.",
116            ErrorKind::OutOfMemory => "System ran out of resources.",
117            ErrorKind::Busy => "The system is busy working on something else.",
118            ErrorKind::Communication => "Communication with a remote party failed.",
119            ErrorKind::Security => "A security fault was detected.",
120            ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
121            ErrorKind::ExternalCancel => "Undocumented.",
122            ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
123            ErrorKind::Unknown => "Unknown error.",
124        }
125    }
126}
127
128impl Error {
129    pub fn new(kind: ErrorKind) -> Error {
130        Error { kind, origin: None }
131    }
132    /// Creates a new instance of an `Error` from a particular TEE error code.
133    ///
134    /// # Examples
135    ///
136    /// ```
137    /// use optee_teec::{Error, ErrorKind};
138    ///
139    /// let error = Error::from_raw_error(0xFFFF000F);
140    /// assert_eq!(error.kind(), ErrorKind::Security);
141    /// ```
142    pub fn from_raw_error(code: u32) -> Error {
143        Error {
144            kind: ErrorKind::from(code),
145            origin: None,
146        }
147    }
148
149    pub fn with_origin(mut self, origin: ErrorOrigin) -> Self {
150        self.origin = Some(origin);
151        self
152    }
153
154    /// Returns the corresponding `ErrorKind` for this error.
155    ///
156    /// # Examples
157    ///
158    /// ```
159    /// use optee_teec::{Error, ErrorKind};
160    ///
161    /// let error = Error::new(ErrorKind::Security);
162    /// ```
163    pub fn kind(&self) -> ErrorKind {
164        self.kind
165    }
166
167    /// Returns the origin of this error.
168    pub fn origin(&self) -> Option<ErrorOrigin> {
169        self.origin.clone()
170    }
171
172    /// Returns raw code of this error.
173    pub fn raw_code(&self) -> u32 {
174        self.kind.into()
175    }
176
177    /// Returns corresponding error message of this error.
178    pub fn message(&self) -> &str {
179        self.kind().as_str()
180    }
181}
182
183impl fmt::Debug for Error {
184    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
185        write!(
186            fmt,
187            "{} (error code 0x{:x}, origin 0x{:x})",
188            self.message(),
189            self.raw_code(),
190            self.origin().map(|v| v.into()).unwrap_or(0_u32),
191        )
192    }
193}
194
195impl fmt::Display for Error {
196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
197        fmt::Debug::fmt(self, f)
198    }
199}
200
201impl std::error::Error for Error {
202    fn description(&self) -> &str {
203        self.message()
204    }
205}
206
207impl From<ErrorKind> for Error {
208    #[inline]
209    fn from(kind: ErrorKind) -> Error {
210        Error { kind, origin: None }
211    }
212}
213
214#[derive(Clone, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive)]
215#[repr(u32)]
216pub enum ErrorOrigin {
217    API = raw::TEEC_ORIGIN_API,
218    COMMS = raw::TEEC_ORIGIN_COMMS,
219    TEE = raw::TEEC_ORIGIN_TEE,
220    TA = raw::TEEC_ORIGIN_TRUSTED_APP,
221    #[default]
222    UNKNOWN,
223}