Skip to main content

cc_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//
18// This file was modified by KylinSoft Co., Ltd. on 2025.
19
20//! TEE 错误处理模块。
21//!
22//! 定义了 TEE Client API 的错误类型体系:
23//! - [`ErrorKind`]:映射 GlobalPlatform TEE 标准错误码
24//! - [`ErrorOrigin`]:标识错误来源(API / Comms / TEE / TA)
25//! - [`Error`]:封装错误类型、来源及格式化输出,支持 `PoisonError` 转换
26
27use std::{fmt, sync::PoisonError};
28
29use num_enum::{FromPrimitive, IntoPrimitive};
30
31use crate::raw;
32
33/// TEE Result 类型。
34pub type Result<T> = std::result::Result<T, Error>;
35
36/// TEE 操作错误类型。
37#[derive(Clone)]
38pub struct Error {
39    kind: ErrorKind,
40    origin: Option<ErrorOrigin>,
41}
42
43/// 指定 TEE 客户端错误通用类别及其在 OP-TEE 客户端库中对应代码的列表。
44#[derive(
45    Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, FromPrimitive, IntoPrimitive,
46)]
47#[repr(u32)]
48pub enum ErrorKind {
49    /// 非特定原因。
50    Generic = raw::TEEC_ERROR_GENERIC,
51    /// 访问权限不足。
52    AccessDenied = raw::TEEC_ERROR_ACCESS_DENIED,
53    /// 操作已取消。
54    Cancel = raw::TEEC_ERROR_CANCEL,
55    /// 并发访问导致冲突。
56    AccessConflict = raw::TEEC_ERROR_ACCESS_CONFLICT,
57    /// 为请求的操作传递了过多数据。
58    ExcessData = raw::TEEC_ERROR_EXCESS_DATA,
59    /// 输入数据格式无效。
60    BadFormat = raw::TEEC_ERROR_BAD_FORMAT,
61    /// 输入参数无效。
62    BadParameters = raw::TEEC_ERROR_BAD_PARAMETERS,
63    /// 在当前状态下操作无效。
64    BadState = raw::TEEC_ERROR_BAD_STATE,
65    /// 未找到请求的数据项。
66    ItemNotFound = raw::TEEC_ERROR_ITEM_NOT_FOUND,
67    /// 请求的操作应该存在但尚未实现。
68    NotImplemented = raw::TEEC_ERROR_NOT_IMPLEMENTED,
69    /// 请求的操作有效,但在此实现中不支持。
70    NotSupported = raw::TEEC_ERROR_NOT_SUPPORTED,
71    /// 缺少预期数据。
72    NoData = raw::TEEC_ERROR_NO_DATA,
73    /// 系统资源耗尽。
74    OutOfMemory = raw::TEEC_ERROR_OUT_OF_MEMORY,
75    /// 系统正忙于处理其他任务。
76    Busy = raw::TEEC_ERROR_BUSY,
77    /// 与远程方的通信失败。
78    Communication = raw::TEEC_ERROR_COMMUNICATION,
79    /// 检测到安全故障。
80    Security = raw::TEEC_ERROR_SECURITY,
81    /// 提供的缓冲区对于生成的输出太短。
82    ShortBuffer = raw::TEEC_ERROR_SHORT_BUFFER,
83    /// 实现定义的错误代码。
84    ExternalCancel = raw::TEEC_ERROR_EXTERNAL_CANCEL,
85    /// 实现定义的错误代码:可信应用程序在操作期间发生崩溃。
86    TargetDead = raw::TEEC_ERROR_TARGET_DEAD,
87    /// 未知错误。
88    #[default]
89    Unknown,
90}
91
92impl ErrorKind {
93    pub(crate) fn as_str(&self) -> &'static str {
94        match self {
95            ErrorKind::Generic => "Non-specific cause.",
96            ErrorKind::AccessDenied => "Access privileges are not sufficient.",
97            ErrorKind::Cancel => "The operation was canceled.",
98            ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
99            ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
100            ErrorKind::BadFormat => "Input data was of invalid format.",
101            ErrorKind::BadParameters => "Input parameters were invalid.",
102            ErrorKind::BadState => "Operation is not valid in the current state.",
103            ErrorKind::ItemNotFound => "The requested data item is not found.",
104            ErrorKind::NotImplemented => {
105                "The requested operation should exist but is not yet implemented."
106            }
107            ErrorKind::NotSupported => {
108                "The requested operation is valid but is not supported in this implementation."
109            }
110            ErrorKind::NoData => "Expected data was missing.",
111            ErrorKind::OutOfMemory => "System ran out of resources.",
112            ErrorKind::Busy => "The system is busy working on something else.",
113            ErrorKind::Communication => "Communication with a remote party failed.",
114            ErrorKind::Security => "A security fault was detected.",
115            ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
116            ErrorKind::ExternalCancel => "Undocumented.",
117            ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
118            ErrorKind::Unknown => "Unknown error.",
119        }
120    }
121}
122
123impl Error {
124    pub fn new(kind: ErrorKind) -> Error {
125        Error { kind, origin: None }
126    }
127
128    /// 从原始 TEE 错误代码创建 Error 实例
129    pub fn from_raw_error(code: u32) -> Error {
130        Error {
131            kind: ErrorKind::from(code),
132            origin: None,
133        }
134    }
135
136    /// 设置错误来源
137    pub fn with_origin(mut self, origin: ErrorOrigin) -> Self {
138        self.origin = Some(origin);
139        self
140    }
141
142    /// 获取错误类型
143    pub fn kind(&self) -> ErrorKind {
144        self.kind
145    }
146
147    /// 获取错误来源
148    pub fn origin(&self) -> Option<ErrorOrigin> {
149        self.origin
150    }
151
152    /// 获取原始错误码(用于 FFI 接口)
153    pub fn raw_code(&self) -> u32 {
154        self.kind.into()
155    }
156
157    /// 获取错误描述信息
158    pub fn message(&self) -> &str {
159        self.kind().as_str()
160    }
161}
162
163impl<T> From<PoisonError<T>> for Error {
164    fn from(_: PoisonError<T>) -> Self {
165        Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API)
166    }
167}
168
169impl fmt::Debug for Error {
170    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
171        write!(
172            fmt,
173            "{} (错误代码 0x{:x}, 来源 0x{:x})",
174            self.message(),
175            self.raw_code(),
176            self.origin().map(|v| v.into()).unwrap_or(0_u32),
177        )
178    }
179}
180
181impl fmt::Display for Error {
182    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
183        fmt::Debug::fmt(self, f)
184    }
185}
186
187impl std::error::Error for Error {
188    fn description(&self) -> &str {
189        self.message()
190    }
191}
192
193impl From<ErrorKind> for Error {
194    #[inline]
195    fn from(kind: ErrorKind) -> Error {
196        Error { kind, origin: None }
197    }
198}
199
200#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, IntoPrimitive)]
201#[repr(u32)]
202pub enum ErrorOrigin {
203    API = raw::TEEC_ORIGIN_API,
204    COMMS = raw::TEEC_ORIGIN_COMMS,
205    TEE = raw::TEEC_ORIGIN_TEE,
206    TA = raw::TEEC_ORIGIN_TRUSTED_APP,
207    #[default]
208    UNKNOWN,
209}
210
211#[cfg(test)]
212mod teec_error_tests {
213    use super::*;
214
215    /// 辅助宏:批量测试 ErrorKind 的 as_str 方法
216    macro_rules! test_error_kind_messages {
217        ($($variant:ident => $msg:expr),* $(,)?) => {
218            $(
219                assert_eq!(ErrorKind::$variant.as_str(), $msg);
220            )*
221        };
222    }
223
224    #[test]
225    fn test_error_types_and_methods() {
226        // 使用宏批量测试所有 ErrorKind 变体的消息
227        test_error_kind_messages! {
228            Generic => "Non-specific cause.",
229            AccessDenied => "Access privileges are not sufficient.",
230            Cancel => "The operation was canceled.",
231            AccessConflict => "Concurrent accesses caused conflict.",
232            ExcessData => "Too much data for the requested operation was passed.",
233            BadFormat => "Input data was of invalid format.",
234            BadParameters => "Input parameters were invalid.",
235            BadState => "Operation is not valid in the current state.",
236            ItemNotFound => "The requested data item is not found.",
237            NotImplemented => "The requested operation should exist but is not yet implemented.",
238            NotSupported => "The requested operation is valid but is not supported in this implementation.",
239            NoData => "Expected data was missing.",
240            OutOfMemory => "System ran out of resources.",
241            Busy => "The system is busy working on something else.",
242            Communication => "Communication with a remote party failed.",
243            Security => "A security fault was detected.",
244            ShortBuffer => "The supplied buffer is too short for the generated output.",
245            ExternalCancel => "Undocumented.",
246            TargetDead => "Trusted Application has panicked during the operation.",
247            Unknown => "Unknown error.",
248        }
249
250        // 测试 Error 的创建和访问方法
251        let error = Error::new(ErrorKind::BadParameters);
252        assert_eq!(error.kind(), ErrorKind::BadParameters);
253        assert_eq!(error.origin(), None);
254
255        // 测试 from_raw_error 方法
256        let raw_error = Error::from_raw_error(ErrorKind::Generic.into());
257        assert_eq!(raw_error.kind(), ErrorKind::Generic);
258
259        // 测试 with_origin 方法
260        let error_with_origin = Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API);
261        assert_eq!(error_with_origin.origin(), Some(ErrorOrigin::API));
262
263        // 测试 raw_code 方法
264        assert_eq!(error.raw_code(), u32::from(ErrorKind::BadParameters));
265
266        // 测试 message 方法
267        assert_eq!(error.message(), "Input parameters were invalid.");
268
269        // 测试 Debug 格式化
270        let debug_str = format!("{:?}", error);
271        assert!(debug_str.contains("错误代码"));
272
273        // 测试 Display 格式化
274        let display_str = format!("{}", error);
275        assert!(display_str.contains("错误代码"));
276
277        // 测试 From trait
278        let from_kind: Error = ErrorKind::OutOfMemory.into();
279        assert_eq!(from_kind.kind(), ErrorKind::OutOfMemory);
280
281        // 测试 ErrorOrigin 的转换
282        assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
283        assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
284        assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
285        assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
286    }
287
288    #[test]
289    fn test_error_kind_all_variants_as_str() {
290        // 测试所有 ErrorKind 变体
291        let error_kinds = vec![
292            ErrorKind::Generic,
293            ErrorKind::AccessDenied,
294            ErrorKind::Cancel,
295            ErrorKind::AccessConflict,
296            ErrorKind::ExcessData,
297            ErrorKind::BadFormat,
298            ErrorKind::BadParameters,
299            ErrorKind::BadState,
300            ErrorKind::ItemNotFound,
301            ErrorKind::NotImplemented,
302            ErrorKind::NotSupported,
303            ErrorKind::NoData,
304            ErrorKind::OutOfMemory,
305            ErrorKind::Busy,
306            ErrorKind::Communication,
307            ErrorKind::Security,
308            ErrorKind::ShortBuffer,
309            ErrorKind::ExternalCancel,
310            ErrorKind::TargetDead,
311            ErrorKind::Unknown,
312        ];
313
314        for kind in error_kinds {
315            let error = Error::new(kind);
316            // 调用 kind 方法不应该崩溃
317            let _ = error.kind();
318        }
319    }
320
321    /// 测试 ErrorOrigin 到 u32 的转换
322    #[test]
323    fn test_error_origin_to_u32() {
324        assert_eq!(u32::from(ErrorOrigin::API), raw::TEEC_ORIGIN_API);
325        assert_eq!(u32::from(ErrorOrigin::COMMS), raw::TEEC_ORIGIN_COMMS);
326        assert_eq!(u32::from(ErrorOrigin::TEE), raw::TEEC_ORIGIN_TEE);
327        assert_eq!(u32::from(ErrorOrigin::TA), raw::TEEC_ORIGIN_TRUSTED_APP);
328    }
329
330    #[test]
331    fn test_error_clone() {
332        let error = Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS);
333        let cloned = error.clone();
334        assert_eq!(cloned.kind(), ErrorKind::Communication);
335        assert_eq!(cloned.origin(), Some(ErrorOrigin::COMMS));
336    }
337
338    #[test]
339    fn test_error_from_poison() {
340        let lock = std::sync::Mutex::new(42u32);
341        let lock_clone = std::sync::Arc::new(lock);
342        let lock_clone2 = lock_clone.clone();
343
344        let handle = std::thread::spawn(move || {
345            let _guard = lock_clone2.lock().unwrap();
346            panic!("intentional panic to poison mutex");
347        });
348        let _ = handle.join();
349
350        let error: Error = lock_clone.lock().unwrap_err().into();
351        assert_eq!(error.kind(), ErrorKind::Generic);
352        assert_eq!(error.origin(), Some(ErrorOrigin::API));
353    }
354
355    #[test]
356    fn test_error_display_with_origin() {
357        let error = Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS);
358        let display = format!("{error}");
359        assert!(display.contains("Communication"));
360        // orig 版本使用数字表示 origin,不是字符串
361        assert!(display.contains("0x"));
362    }
363
364    #[test]
365    fn test_error_display_no_origin() {
366        let error = Error::new(ErrorKind::OutOfMemory);
367        let display = format!("{error}");
368        assert!(display.contains("resources"));
369    }
370
371    #[test]
372    fn test_error_debug_format() {
373        let error = Error::new(ErrorKind::Security).with_origin(ErrorOrigin::TEE);
374        let debug = format!("{error:?}");
375        // orig 版本的 Debug 格式包含错误消息和代码
376        assert!(debug.contains("security") || debug.contains("fault"));
377        // orig 版本使用数字表示 origin
378        assert!(debug.contains("0x"));
379    }
380
381    #[test]
382    fn test_error_origin_unknown() {
383        assert_eq!(u32::from(ErrorOrigin::UNKNOWN), 5);
384        assert_eq!(ErrorOrigin::from(5), ErrorOrigin::UNKNOWN);
385    }
386}