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 
18 use optee_teec_sys as raw;
19 use std::fmt;
20 
21 /// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
22 /// type for TEE operations.
23 ///
24 /// # Examples
25 ///
26 /// ``` no_run
27 /// fn main() -> optee_teec::Result<()> {
28 ///     let mut ctx = Context::new()?;
29 /// }
30 /// ````
31 pub type Result<T> = std::result::Result<T, Error>;
32 
33 /// The error type for TEE operations of [`Context`] and [`Session`].
34 ///
35 /// [`Context`]: struct.Context.html
36 /// [`Session`]: struct.Session.html
37 pub struct Error {
38     code: u32,
39 }
40 
41 /// A list specifying general categories of TEE client error and its
42 /// corresponding code in OP-TEE client library.
43 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
44 #[repr(u32)]
45 pub enum ErrorKind {
46     /// Non-specific cause.
47     Generic = 0xFFFF0000,
48     /// Access privileges are not sufficient.
49     AccessDenied = 0xFFFF0001,
50     /// The operation was canceled.
51     Cancel = 0xFFFF0002,
52     /// Concurrent accesses caused conflict.
53     AccessConflict = 0xFFFF0003,
54     /// Too much data for the requested operation was passed.
55     ExcessData = 0xFFFF0004,
56     /// Input data was of invalid format.
57     BadFormat = 0xFFFF0005,
58     /// Input parameters were invalid.
59     BadParameters = 0xFFFF0006,
60     /// Operation is not valid in the current state.
61     BadState = 0xFFFF0007,
62     /// The requested data item is not found.
63     ItemNotFound = 0xFFFF0008,
64     /// The requested operation should exist but is not yet implemented.
65     NotImplemented = 0xFFFF0009,
66     /// The requested operation is valid but is not supported in this implementation.
67     NotSupported = 0xFFFF000A,
68     /// Expected data was missing.
69     NoData = 0xFFFF000B,
70     /// System ran out of resources.
71     OutOfMEmory = 0xFFFF000C,
72     /// The system is busy working on something else.
73     Busy = 0xFFFF000D,
74     /// Communication with a remote party failed.
75     Communication = 0xFFFF000E,
76     /// A security fault was detected.
77     Security = 0xFFFF000F,
78     /// The supplied buffer is too short for the generated output.
79     ShortBuffer = 0xFFFF0010,
80     /// Implementation defined error code.
81     ExternalCancel = 0xFFFF0011,
82     /// Implementation defined error code: trusted Application has panicked during the operation.
83     TargetDead = 0xFFFF3024,
84     /// Unknown error.
85     Unknown,
86 }
87 
88 impl ErrorKind {
as_str(&self) -> &'static str89     pub(crate) fn as_str(&self) -> &'static str {
90         match *self {
91             ErrorKind::Generic => "Non-specific cause.",
92             ErrorKind::AccessDenied => "Access privileges are not sufficient.",
93             ErrorKind::Cancel => "The operation was canceled.",
94             ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
95             ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
96             ErrorKind::BadFormat => "Input data was of invalid format.",
97             ErrorKind::BadParameters => "Input parameters were invalid.",
98             ErrorKind::BadState => "Operation is not valid in the current state.",
99             ErrorKind::ItemNotFound => "The requested data item is not found.",
100             ErrorKind::NotImplemented => {
101                 "The requested operation should exist but is not yet implemented."
102             }
103             ErrorKind::NotSupported => {
104                 "The requested operation is valid but is not supported in this implementation."
105             }
106             ErrorKind::NoData => "Expected data was missing.",
107             ErrorKind::OutOfMEmory => "System ran out of resources.",
108             ErrorKind::Busy => "The system is busy working on something else.",
109             ErrorKind::Communication => "Communication with a remote party failed.",
110             ErrorKind::Security => "A security fault was detected.",
111             ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
112             ErrorKind::ExternalCancel => "Undocumented.",
113             ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
114             ErrorKind::Unknown => "Unknown error.",
115         }
116     }
117 }
118 
119 impl Error {
new(kind: ErrorKind) -> Error120     pub fn new(kind: ErrorKind) -> Error {
121         Error { code: kind as u32 }
122     }
123     /// Creates a new instance of an `Error` from a particular TEE error code.
124     ///
125     /// # Examples
126     ///
127     /// ``` no_run
128     /// use optee_teec;
129     ///
130     /// let error = optee_teec::Error::from_raw_error(0xFFFF000F);
131     /// assert_eq!(error.kind(), optee_teec::ErrorKind::Security);
132     /// ```
from_raw_error(code: u32) -> Error133     pub fn from_raw_error(code: u32) -> Error {
134         Error { code }
135     }
136 
137     /// Returns the corresponding `ErrorKind` for this error.
138     ///
139     /// # Examples
140     ///
141     /// ``` no_run
142     /// use optee_teec;
143     ///
144     /// let error = optee_teec::Error::new(optee_teec::ErrorKind::Security);
145     /// ```
kind(&self) -> ErrorKind146     pub fn kind(&self) -> ErrorKind {
147         match self.code {
148             raw::TEEC_ERROR_GENERIC => ErrorKind::Generic,
149             raw::TEEC_ERROR_ACCESS_DENIED => ErrorKind::AccessDenied,
150             raw::TEEC_ERROR_CANCEL => ErrorKind::Cancel,
151             raw::TEEC_ERROR_ACCESS_CONFLICT => ErrorKind::AccessConflict,
152             raw::TEEC_ERROR_EXCESS_DATA => ErrorKind::ExcessData,
153             raw::TEEC_ERROR_BAD_FORMAT => ErrorKind::BadFormat,
154             raw::TEEC_ERROR_BAD_PARAMETERS => ErrorKind::BadParameters,
155             raw::TEEC_ERROR_BAD_STATE => ErrorKind::BadState,
156             raw::TEEC_ERROR_ITEM_NOT_FOUND => ErrorKind::ItemNotFound,
157             raw::TEEC_ERROR_NOT_IMPLEMENTED => ErrorKind::NotImplemented,
158             raw::TEEC_ERROR_NOT_SUPPORTED => ErrorKind::NotSupported,
159             raw::TEEC_ERROR_NO_DATA => ErrorKind::NoData,
160             raw::TEEC_ERROR_OUT_OF_MEMORY => ErrorKind::OutOfMEmory,
161             raw::TEEC_ERROR_BUSY => ErrorKind::Busy,
162             raw::TEEC_ERROR_COMMUNICATION => ErrorKind::Communication,
163             raw::TEEC_ERROR_SECURITY => ErrorKind::Security,
164             raw::TEEC_ERROR_SHORT_BUFFER => ErrorKind::ShortBuffer,
165             raw::TEEC_ERROR_EXTERNAL_CANCEL => ErrorKind::ExternalCancel,
166             raw::TEEC_ERROR_TARGET_DEAD => ErrorKind::TargetDead,
167             _ => ErrorKind::Unknown,
168         }
169     }
170 
171     /// Returns raw code of this error.
raw_code(&self) -> u32172     pub fn raw_code(&self) -> u32 {
173         self.code
174     }
175 
176     /// Returns corresponding error message of this error.
message(&self) -> &str177     pub fn message(&self) -> &str {
178         self.kind().as_str()
179     }
180 }
181 
182 impl fmt::Debug for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result183     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
184         write!(fmt, "{} (error code 0x{:x})", self.message(), self.code)
185     }
186 }
187 
188 impl fmt::Display for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result189     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
190         write!(fmt, "{} (error code 0x{:x})", self.message(), self.code)
191     }
192 }
193 
194 impl std::error::Error for Error {
description(&self) -> &str195     fn description(&self) -> &str {
196         self.message()
197     }
198 }
199 
200 impl From<ErrorKind> for Error {
201     #[inline]
from(kind: ErrorKind) -> Error202     fn from(kind: ErrorKind) -> Error {
203         Error { code: kind as u32 }
204     }
205 }
206