Skip to main content

cc_teec/teec/
c_api.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (C) 2025-2026 KylinSoft Co., Ltd. <https://www.kylinos.cn/>
3// See LICENSES for license details.
4
5//! GlobalPlatform TEE Client API — 对外 C 接口层
6//!
7//! 本模块是所有 `TEEC_*` FFI 函数的唯一入口,每个函数都是一个薄包装:
8//!
9//! 1. 打印调试日志
10//! 2. 调用对应子模块中的 `_impl` 领域逻辑函数(或 `SharedMemoryManager` 方法)
11//! 3. 通过 `handle_error` 将 `Result` 转换为 C 风格的 `TEEC_Result` + `ret_origin`
12//!
13//! 这种集中编排使得:
14//! - C API 全貌一目了然(审计友好)
15//! - 领域模块(`context`、`session`、`shared_memory`)只关心业务逻辑
16//! - 编译优化(`_impl` 函数小、易内联)
17
18use std::ffi::{c_char, c_void};
19
20use log::{debug, warn};
21
22use super::{
23    context::{ContextManager, initialize_context_impl},
24    safe_ptr,
25    session::{
26        close_session_impl, invoke_command_impl, open_session_impl, request_cancellation_impl,
27    },
28    shared_memory::SharedMemoryManager,
29};
30use crate::{ErrorKind, ErrorOrigin, Result, raw};
31
32/// 统一的错误处理入口:将 `Result<u32>` 映射为 C 风格返回值。
33///
34/// - 成功时直接返回 `u32` 结果码
35/// - 失败时通过 `ret_origin` 指针(若非空)写入错误来源,
36///   并返回 `Error::raw_code()` 对应的 TEEC_Result 错误码
37fn handle_error(result: Result<u32>, ret_origin: *mut u32) -> raw::TEEC_Result {
38    match result {
39        Ok(code) => code,
40        Err(e) => {
41            if !ret_origin.is_null() {
42                // SAFETY: `ret_origin` 已通过 null 检查验证为非空指针。
43                // 写入 u32 值是安全的,调用方保证指针有效且可写。
44                unsafe {
45                    *ret_origin = e.origin().unwrap_or(ErrorOrigin::API) as u32;
46                }
47            }
48            e.raw_code()
49        }
50    }
51}
52
53/// TEEC_InitializeContext() - 初始化 TEE 上下文,建立与 TEE 的机密通信连接。
54///
55/// @param name  可选的名称字符串(当前实现忽略)。
56/// @param ctx   要初始化的上下文结构指针。
57///
58/// @return TEEC_SUCCESS       上下文初始化成功。
59/// @return TEEC_Result        出现错误。
60#[unsafe(no_mangle)]
61pub extern "C" fn TEEC_InitializeContext(
62    _name: *const c_char,
63    ctx: *mut raw::TEEC_Context,
64) -> raw::TEEC_Result {
65    debug!("TEEC_InitializeContext");
66
67    match initialize_context_impl(ctx) {
68        Ok(_) => raw::TEEC_SUCCESS,
69        Err(e) => e.raw_code(),
70    }
71}
72
73/// TEEC_FinalizeContext() - 销毁保存连接信息的上下文。
74///
75/// 该函数用于销毁已初始化的 TEE 上下文,关闭客户端应用与 TEE 之间的连接。
76/// 仅当与该上下文关联的所有会话已关闭且所有共享内存块已释放时才可调用。
77///
78/// @param ctx  要销毁的上下文。
79#[unsafe(no_mangle)]
80pub extern "C" fn TEEC_FinalizeContext(ctx: *mut raw::TEEC_Context) {
81    debug!("[HOST] TEEC_FinalizeContext");
82
83    if let Ok(ctx_nn) = safe_ptr::deref(ctx) {
84        // SAFETY: `ctx_nn` 已由 `deref` 验证为非空。`as_ref()` 返回的不可变引用
85        // 在此作用域内有效。
86        let ctx_ref = unsafe { ctx_nn.as_ref() };
87        let ctx_id = ctx_ref.imp.fd;
88        if ctx_id < 0 {
89            debug!("TEEC_FinalizeContext: context already finalized (fd={ctx_id})");
90            return;
91        }
92    }
93
94    SharedMemoryManager::release_by_context(ctx);
95    ContextManager::remove_context(ctx);
96}
97
98/// TEEC_OpenSession() - 与指定的受信任应用打开一个新会话。
99///
100/// @param ctx                已初始化的 TEE 上下文,在其作用域内打开会话。
101/// @param session            要初始化的会话结构体指针。
102/// @param destination        标识要打开会话的受信任应用的 UUID 结构。
103/// @param connection_method  要使用的连接方法。
104/// @param connection_data    与所选连接方法有关的连接数据。本实现不支持,
105///                           应设置为 NULL。
106/// @param operation          用于会话的操作结构。若不需要则传入 NULL。
107/// @param ret_origin         若函数返回非 TEEC_SUCCESS,此参数将保存错误来源。
108///
109/// @return TEEC_SUCCESS      成功打开会话。
110/// @return TEEC_Result       出现错误。
111#[unsafe(no_mangle)]
112pub extern "C" fn TEEC_OpenSession(
113    ctx: *mut raw::TEEC_Context,
114    session: *mut raw::TEEC_Session,
115    destination: *const raw::TEEC_UUID,
116    connection_method: u32,
117    _connection_data: *const c_void,
118    operation: *mut raw::TEEC_Operation,
119    ret_origin: *mut u32,
120) -> raw::TEEC_Result {
121    debug!("TEEC_OpenSession");
122
123    let result = open_session_impl(ctx, session, destination, connection_method, operation);
124
125    handle_error(result, ret_origin)
126}
127
128/// TEEC_CloseSession() - 关闭已与受信任应用打开的会话。
129///
130/// @param session 要关闭的会话。
131#[unsafe(no_mangle)]
132pub extern "C" fn TEEC_CloseSession(session: *mut raw::TEEC_Session) {
133    debug!("TEEC_CloseSession");
134
135    if let Err(e) = close_session_impl(session) {
136        // CloseSession 失败不应该阻断清理,但需要记录错误以便调试
137        warn!("TEEC_CloseSession 失败:{e}");
138    }
139}
140
141/// TEEC_InvokeCommand() - 在指定的受信任应用中执行命令。
142///
143/// @param session        已打开的受信任应用会话句柄。
144/// @param cmd_id         要在受信任应用中调用的命令标识符。
145/// @param operation      用于调用命令的操作结构;若不需要则传入 NULL。
146/// @param error_origin   若函数返回非 TEEC_SUCCESS,此参数将保存错误来源。
147///
148/// @return TEEC_SUCCESS  操作成功。
149/// @return TEEC_Result   出现错误。
150#[unsafe(no_mangle)]
151pub extern "C" fn TEEC_InvokeCommand(
152    session: *mut raw::TEEC_Session,
153    cmd_id: u32,
154    operation: *mut raw::TEEC_Operation,
155    error_origin: *mut u32,
156) -> raw::TEEC_Result {
157    debug!("TEEC_InvokeCommand");
158
159    let result = invoke_command_impl(session, cmd_id, operation);
160
161    handle_error(result, error_origin)
162}
163
164/// TEEC_RequestCancellation() - 请求取消正在等待的打开会话或命令调用。
165///
166/// @param operation 指向先前传递给 open session 或 invoke 的操作结构的指针。
167#[unsafe(no_mangle)]
168pub extern "C" fn TEEC_RequestCancellation(operation: *mut raw::TEEC_Operation) {
169    debug!("TEEC_RequestCancellation");
170
171    if let Err(e) = request_cancellation_impl(operation) {
172        // RequestCancellation 失败不应该阻断,但需要记录错误以便调试
173        warn!("TEEC_RequestCancellation 失败:{e}");
174    }
175}
176
177/// TEEC_RegisterSharedMemory() - 将现有内存块注册为在指定上下文作用域内的
178/// 共享内存块。
179///
180/// @param ctx       已初始化的 TEE 上下文。
181/// @param sharedMem 要注册的共享内存结构指针。
182///
183/// @return TEEC_SUCCESS              注册成功。
184/// @return TEEC_ERROR_OUT_OF_MEMORY  内存不足。
185/// @return TEEC_Result               其他错误。
186#[unsafe(no_mangle)]
187pub extern "C" fn TEEC_RegisterSharedMemory(
188    ctx: *mut raw::TEEC_Context,
189    shm: *mut raw::TEEC_SharedMemory,
190) -> raw::TEEC_Result {
191    debug!("TEEC_RegisterSharedMemory");
192
193    match SharedMemoryManager::allocate(ctx, shm, true) {
194        Ok(_) => raw::TEEC_SUCCESS,
195        Err(e) => e.raw_code(),
196    }
197}
198
199/// TEEC_RegisterSharedMemoryFileDescriptor() - 通过文件描述符注册共享内存。
200///
201/// @param ctx    已初始化的 TEE 上下文。
202/// @param shm    指向共享内存结构的指针。
203/// @param fd     要注册的共享内存文件描述符。
204///
205/// @return TEEC_ERROR_NOT_IMPLEMENTED  当前版本未实现此功能。
206#[unsafe(no_mangle)]
207pub extern "C" fn TEEC_RegisterSharedMemoryFileDescriptor(
208    _ctx: *mut raw::TEEC_Context,
209    _shm: *mut raw::TEEC_SharedMemory,
210    _fd: i32,
211) -> raw::TEEC_Result {
212    // TODO: 实现此函数
213    ErrorKind::NotImplemented.into()
214}
215
216/// TEEC_AllocateSharedMemory() - 为 TEE 分配共享内存。
217///
218/// @param ctx        已初始化的 TEE 上下文。
219/// @param sharedMem  指向要分配的共享内存结构的指针(由调用者填写希望的属性)。
220///
221/// @return TEEC_SUCCESS              分配/注册成功。
222/// @return TEEC_ERROR_OUT_OF_MEMORY  内存不足。
223/// @return TEEC_Result               其他错误。
224#[unsafe(no_mangle)]
225pub extern "C" fn TEEC_AllocateSharedMemory(
226    ctx: *mut raw::TEEC_Context,
227    shm: *mut raw::TEEC_SharedMemory,
228) -> raw::TEEC_Result {
229    debug!("TEEC_AllocateSharedMemory");
230
231    match SharedMemoryManager::allocate(ctx, shm, false) {
232        Ok(_) => raw::TEEC_SUCCESS,
233        Err(e) => e.raw_code(),
234    }
235}
236
237/// TEEC_ReleaseSharedMemory() - 释放或取消注册共享内存。
238///
239/// @param sharedMem  要释放或取消注册的共享内存指针。
240#[unsafe(no_mangle)]
241pub extern "C" fn TEEC_ReleaseSharedMemory(shm: *mut raw::TEEC_SharedMemory) {
242    debug!("TEEC_ReleaseSharedMemory");
243    SharedMemoryManager::release(shm);
244}