#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#[cfg(feature = "ca-sign-verify")]
mod ca_auth;
mod context;
mod operation;
mod safe_ptr;
mod shared_memory;
#[cfg(feature = "ca-sign-verify")]
pub use ca_auth::{clear_cache, get_or_verify_ca};
pub use context::ContextManager;
pub use operation::{build_parameters_from_operation, update_operation_from_parameters};
pub use shared_memory::SharedMemoryManager;
use std::{
ffi::{c_char, c_void},
ptr,
sync::{
LazyLock,
atomic::{AtomicI32, Ordering},
},
};
use crate::{Error, ErrorKind, ErrorOrigin, Result, cc_client::client::CcClient, raw};
use teec_protocol::{PacketType, TEE_Parameters, TEE_Request, TEE_Response};
use log::{debug, warn};
use postcard::{take_from_bytes, to_allocvec};
use uuid::Uuid;
static CONTEXT_ID_COUNTER: LazyLock<AtomicI32> = LazyLock::new(|| AtomicI32::new(-1));
fn uuid_to_string(uuid: &raw::TEEC_UUID) -> Result<String> {
let bytes: [u8; 16] = [
(uuid.timeLow >> 24) as u8,
(uuid.timeLow >> 16) as u8,
(uuid.timeLow >> 8) as u8,
uuid.timeLow as u8,
(uuid.timeMid >> 8) as u8,
uuid.timeMid as u8,
(uuid.timeHiAndVersion >> 8) as u8,
uuid.timeHiAndVersion as u8,
uuid.clockSeqAndNode[0],
uuid.clockSeqAndNode[1],
uuid.clockSeqAndNode[2],
uuid.clockSeqAndNode[3],
uuid.clockSeqAndNode[4],
uuid.clockSeqAndNode[5],
uuid.clockSeqAndNode[6],
uuid.clockSeqAndNode[7],
];
Uuid::from_slice(&bytes)
.map(|u| u.to_string())
.map_err(|_| Error::new(ErrorKind::BadFormat))
}
fn handle_error(result: Result<u32>, ret_origin: *mut u32) -> raw::TEEC_Result {
match result {
Ok(code) => code,
Err(e) => {
if !ret_origin.is_null() {
unsafe {
*ret_origin = e.origin().unwrap_or(ErrorOrigin::API) as u32;
}
}
e.raw_code()
}
}
}
fn send_request_and_recv_response(
ctx: *mut raw::TEEC_Context,
packet_type: PacketType,
request: &TEE_Request,
) -> Result<TEE_Response> {
let client_arc = ContextManager::get_client(ctx)?;
let mut client = client_arc
.lock()
.map_err(|_| Error::new(ErrorKind::Generic).with_origin(ErrorOrigin::API))?;
let request_data = to_allocvec(request).map_err(|e| {
warn!("序列化请求失败:{e}");
Error::new(ErrorKind::BadFormat).with_origin(ErrorOrigin::API)
})?;
const MAX_REQUEST_SIZE: usize = 64 * 1024 * 1024;
if request_data.len() > MAX_REQUEST_SIZE {
warn!(
"请求数据过大:{} bytes (最大允许 {} bytes)",
request_data.len(),
MAX_REQUEST_SIZE
);
return Err(Error::new(ErrorKind::BadFormat).with_origin(ErrorOrigin::API));
}
client
.send_data_with_header(packet_type, &request_data)
.map_err(|e| {
warn!("发送请求失败:{e}");
Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS)
})?;
let mut len_buf = [0u8; 4];
client.recv_data(&mut len_buf).map_err(|e| {
warn!("接收响应长度失败:{e}");
Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS)
})?;
let response_len_u32 = u32::from_ne_bytes(len_buf);
const MAX_RESPONSE_SIZE: usize = 64 * 1024 * 1024;
if response_len_u32 > MAX_RESPONSE_SIZE as u32 {
warn!(
"响应数据过大:{} bytes (最大允许 {} bytes)",
response_len_u32, MAX_RESPONSE_SIZE
);
return Err(Error::new(ErrorKind::BadFormat).with_origin(ErrorOrigin::COMMS));
}
let response_len = response_len_u32 as usize;
let mut response_data = vec![0u8; response_len];
client.recv_data(&mut response_data).map_err(|e| {
warn!("接收响应数据失败:{e}");
Error::new(ErrorKind::Communication).with_origin(ErrorOrigin::COMMS)
})?;
take_from_bytes::<TEE_Response>(&response_data)
.map(|(response, _)| response)
.map_err(|e| {
warn!("反序列化响应失败:{e}");
Error::new(ErrorKind::BadFormat).with_origin(ErrorOrigin::API)
})
}
fn set_ret_origin(p: *mut u32, v: u32) -> Result<()> {
safe_ptr::write_raw(p, v)
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_InitializeContext(
_name: *const c_char,
ctx: *mut raw::TEEC_Context,
) -> raw::TEEC_Result {
debug!("TEEC_InitializeContext");
let result = (|| -> Result<()> {
let mut ctx_nn = safe_ptr::deref_mut(ctx)?;
let ctx_ref = unsafe { ctx_nn.as_mut() };
let client = CcClient::init().map_err(|e| {
warn!("TEEC_InitializeContext:初始化机密通信上下文失败:{e}");
Error::new(ErrorKind::Communication)
})?;
let id = CONTEXT_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
ctx_ref.imp.fd = id;
ctx_ref.imp.reg_mem = true;
ctx_ref.imp.memref_null = true;
ContextManager::add_context(ctx, client)
})();
match result {
Ok(_) => raw::TEEC_SUCCESS,
Err(e) => e.raw_code(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_FinalizeContext(ctx: *mut raw::TEEC_Context) {
debug!("TEEC_FinalizeContext");
SharedMemoryManager::release_by_context(ctx);
ContextManager::remove_context(ctx);
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_OpenSession(
ctx: *mut raw::TEEC_Context,
session: *mut raw::TEEC_Session,
destination: *const raw::TEEC_UUID,
connection_method: u32,
_connection_data: *const c_void,
operation: *mut raw::TEEC_Operation,
ret_origin: *mut u32,
) -> raw::TEEC_Result {
debug!("TEEC_OpenSession");
let result = (|| -> Result<u32> {
let _ = safe_ptr::deref_mut(ctx)?;
let _ = safe_ptr::deref_mut(session)?;
let uuid_nn = safe_ptr::deref(destination)?;
let uuid = unsafe { uuid_nn.as_ref() };
let uuid_str = uuid_to_string(uuid)?;
#[cfg(feature = "ca-sign-verify")]
let ca_auth_info = {
use teec_protocol::CaAuthInfo;
let auth_result = get_or_verify_ca();
if !auth_result.verified {
warn!("CA 签名验证失败: ca_uuid={}", auth_result.ca_uuid);
} else {
debug!("CA 签名验证通过: ca_uuid={}", auth_result.ca_uuid);
}
Some(CaAuthInfo {
ca_uuid: auth_result.ca_uuid,
verified: auth_result.verified,
})
};
#[cfg(not(feature = "ca-sign-verify"))]
let ca_auth_info: Option<teec_protocol::CaAuthInfo> = None;
let params = if operation.is_null() {
TEE_Parameters::default()
} else {
build_parameters_from_operation(operation)?
};
let request = TEE_Request::OpenSession {
uuid: uuid_str,
connection_method,
params,
ca_auth_info,
};
let mut session_nn = safe_ptr::deref_mut(session)?;
let session_ref = unsafe { session_nn.as_mut() };
let response = send_request_and_recv_response(ctx, PacketType::OpenSession, &request)?;
match response {
TEE_Response::OpenSession { session_id, result } => {
debug!("TEEC_OpenSession: 接收 session_id 和结果: {session_id}, {result}");
session_ref.imp.ctx = ctx;
session_ref.imp.session_id = session_id;
let _ = set_ret_origin(ret_origin, ErrorOrigin::TEE.into());
Ok(result)
}
_ => Err(Error::new(ErrorKind::BadParameters).with_origin(ErrorOrigin::API)),
}
})();
handle_error(result, ret_origin)
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_CloseSession(session: *mut raw::TEEC_Session) {
debug!("TEEC_CloseSession");
let result = (|| -> Result<()> {
let mut session_nn = safe_ptr::deref_mut(session)?;
let session_ref = unsafe { session_nn.as_mut() };
let session_id = session_ref.imp.session_id;
let ctx = session_ref.imp.ctx;
if ctx.is_null() {
return Err(Error::new(ErrorKind::BadParameters));
}
let request = TEE_Request::CloseSession { session_id };
let response = send_request_and_recv_response(ctx, PacketType::CloseSession, &request)?;
match response {
TEE_Response::CloseSession { result } => {
debug!("TEEC_CloseSession: 接收结果: {result}");
session_ref.imp.ctx = ptr::null_mut();
session_ref.imp.session_id = 0;
Ok(())
}
_ => Err(Error::new(ErrorKind::BadParameters)),
}
})();
if let Err(e) = result {
warn!("TEEC_CloseSession 失败:{e}");
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_InvokeCommand(
session: *mut raw::TEEC_Session,
cmd_id: u32,
operation: *mut raw::TEEC_Operation,
error_origin: *mut u32,
) -> raw::TEEC_Result {
debug!("TEEC_InvokeCommand");
let result = (|| -> Result<u32> {
let mut session_nn = safe_ptr::deref_mut(session)?;
let session_ref = unsafe { session_nn.as_mut() };
let session_id = session_ref.imp.session_id;
let ctx = session_ref.imp.ctx;
if ctx.is_null() {
return Err(Error::new(ErrorKind::BadParameters));
}
let params = if operation.is_null() {
TEE_Parameters::default()
} else {
let mut operation_nn = safe_ptr::deref_mut(operation)?;
let operation_ref = unsafe { operation_nn.as_mut() };
operation_ref.imp.session = session;
build_parameters_from_operation(operation)?
};
let request = TEE_Request::InvokeCommand {
session_id,
cmd_id,
params,
};
let response = send_request_and_recv_response(ctx, PacketType::InvokeCommand, &request)?;
match response {
TEE_Response::InvokeCommand { params, result } => {
if result != raw::TEEC_SUCCESS {
let origin = if result == raw::TEEC_ERROR_TARGET_DEAD {
ErrorOrigin::TEE
} else {
ErrorOrigin::API
};
return Err(Error::new(ErrorKind::from(result)).with_origin(origin));
}
if !operation.is_null() {
update_operation_from_parameters(operation, params)?;
}
Ok(result)
}
_ => Err(Error::new(ErrorKind::BadParameters).with_origin(ErrorOrigin::API)),
}
})();
handle_error(result, error_origin)
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_RegisterSharedMemory(
ctx: *mut raw::TEEC_Context,
shm: *mut raw::TEEC_SharedMemory,
) -> raw::TEEC_Result {
debug!("TEEC_RegisterSharedMemory");
let result = SharedMemoryManager::allocate(ctx, shm, true);
match result {
Ok(_) => raw::TEEC_SUCCESS,
Err(e) => e.raw_code(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_RegisterSharedMemoryFileDescriptor(
_ctx: *mut raw::TEEC_Context,
_shm: *mut raw::TEEC_SharedMemory,
_fd: i32,
) -> raw::TEEC_Result {
ErrorKind::NotImplemented.into()
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_AllocateSharedMemory(
ctx: *mut raw::TEEC_Context,
shm: *mut raw::TEEC_SharedMemory,
) -> raw::TEEC_Result {
debug!("TEEC_AllocateSharedMemory");
match SharedMemoryManager::allocate(ctx, shm, false) {
Ok(_) => raw::TEEC_SUCCESS,
Err(e) => e.raw_code(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_ReleaseSharedMemory(shm: *mut raw::TEEC_SharedMemory) {
debug!("TEEC_ReleaseSharedMemory");
SharedMemoryManager::release(shm);
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_RequestCancellation(operation: *mut raw::TEEC_Operation) {
debug!("TEEC_RequestCancellation");
let result = (|| -> Result<()> {
let mut operation_nn = safe_ptr::deref_mut(operation)?;
let operation_ref = unsafe { operation_nn.as_mut() };
let session = operation_ref.imp.session;
if session.is_null() {
return Ok(());
}
let mut session_nn = safe_ptr::deref_mut(session)?;
let session_ref = unsafe { session_nn.as_mut() };
let session_id = session_ref.imp.session_id;
let ctx = session_ref.imp.ctx;
if ctx.is_null() {
return Ok(());
}
let request = TEE_Request::RequestCancellation { session_id };
let response =
send_request_and_recv_response(ctx, PacketType::RequestCancellation, &request)?;
match response {
TEE_Response::RequestCancellation { result: _ } => {
debug!("TEEC_RequestCancellation: 接收结果");
Ok(())
}
_ => Err(Error::new(ErrorKind::BadParameters)),
}
})();
if let Err(e) = result {
warn!("TEEC_RequestCancellation 失败:{e}");
}
}