use std::ffi::{c_char, c_void};
use log::{debug, warn};
use super::{
context::{ContextManager, initialize_context_impl},
safe_ptr,
session::{
close_session_impl, invoke_command_impl, open_session_impl, request_cancellation_impl,
},
shared_memory::SharedMemoryManager,
};
use crate::{ErrorKind, ErrorOrigin, Result, raw};
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()
}
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_InitializeContext(
_name: *const c_char,
ctx: *mut raw::TEEC_Context,
) -> raw::TEEC_Result {
debug!("TEEC_InitializeContext");
match initialize_context_impl(ctx) {
Ok(_) => raw::TEEC_SUCCESS,
Err(e) => e.raw_code(),
}
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_FinalizeContext(ctx: *mut raw::TEEC_Context) {
debug!("[HOST] TEEC_FinalizeContext");
if !ContextManager::is_registered(ctx) {
debug!("TEEC_FinalizeContext: ctx 未初始化,忽略");
return;
}
if let Ok(ctx_nn) = safe_ptr::deref(ctx) {
let ctx_ref = unsafe { ctx_nn.as_ref() };
let ctx_id = ctx_ref.imp.fd;
if ctx_id < 0 {
debug!("TEEC_FinalizeContext: context already finalized (fd={ctx_id})");
return;
}
}
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 = open_session_impl(ctx, session, destination, connection_method, operation);
handle_error(result, ret_origin)
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_CloseSession(session: *mut raw::TEEC_Session) {
debug!("TEEC_CloseSession");
if let Err(e) = close_session_impl(session) {
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 = invoke_command_impl(session, cmd_id, operation);
handle_error(result, error_origin)
}
#[unsafe(no_mangle)]
pub extern "C" fn TEEC_RequestCancellation(operation: *mut raw::TEEC_Operation) {
debug!("TEEC_RequestCancellation");
if let Err(e) = request_cancellation_impl(operation) {
warn!("TEEC_RequestCancellation 失败:{e}");
}
}
#[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");
match SharedMemoryManager::allocate(ctx, shm, true) {
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);
}
#[cfg(test)]
mod c_api_tests {
use std::ptr;
use super::*;
#[test]
fn test_invoke_command_null_session() {
let res = TEEC_InvokeCommand(ptr::null_mut(), 0, ptr::null_mut(), ptr::null_mut());
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_invoke_command_uninitialized_session() {
let mut session = raw::TEEC_Session {
imp: raw::TEEC_Session__Imp {
ctx: ptr::null_mut(),
session_id: 0,
},
};
let mut error_origin = 0u32;
let res = TEEC_InvokeCommand(&mut session, 1, ptr::null_mut(), &mut error_origin);
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_register_shared_memory_null_args() {
let res = TEEC_RegisterSharedMemory(ptr::null_mut(), ptr::null_mut());
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_register_shared_memory_null_buffer() {
let mut ctx = raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: -1,
reg_mem: false,
memref_null: false,
},
};
let mut shm = raw::TEEC_SharedMemory {
buffer: ptr::null_mut(),
size: 1024,
flags: raw::TEEC_MEM_INPUT,
imp: raw::TEEC_SharedMemory__Imp {
id: -1,
alloced_size: 0,
shadow_buffer: ptr::null_mut(),
registered_fd: -1,
flags: 0,
},
};
let res = TEEC_RegisterSharedMemory(&mut ctx, &mut shm);
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_request_cancellation_null_operation() {
TEEC_RequestCancellation(ptr::null_mut());
}
#[test]
fn test_request_cancellation_detached_operation() {
let mut operation = raw::TEEC_Operation {
started: 1,
paramTypes: 0,
params: [unsafe { std::mem::zeroed() }; 4],
imp: raw::TEEC_Operation__Imp {
session: ptr::null_mut(),
},
};
TEEC_RequestCancellation(&mut operation);
}
#[test]
fn test_initialize_context_null_ctx() {
let res = TEEC_InitializeContext(ptr::null(), ptr::null_mut());
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_initialize_context_no_tee() {
let mut ctx = raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: -1,
reg_mem: false,
memref_null: false,
},
};
let _ = TEEC_InitializeContext(ptr::null(), &mut ctx);
}
#[test]
fn test_open_session_null_args() {
let res = TEEC_OpenSession(
ptr::null_mut(),
ptr::null_mut(),
ptr::null(),
0,
ptr::null(),
ptr::null_mut(),
ptr::null_mut(),
);
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_open_session_null_destination() {
let mut ctx = raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: -1,
reg_mem: false,
memref_null: false,
},
};
let mut session = raw::TEEC_Session {
imp: raw::TEEC_Session__Imp {
ctx: ptr::null_mut(),
session_id: 0,
},
};
let res = TEEC_OpenSession(
&mut ctx,
&mut session,
ptr::null(),
0,
ptr::null(),
ptr::null_mut(),
ptr::null_mut(),
);
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_close_session_null() {
TEEC_CloseSession(ptr::null_mut());
}
#[test]
fn test_close_session_uninitialized() {
let mut session = raw::TEEC_Session {
imp: raw::TEEC_Session__Imp {
ctx: ptr::null_mut(),
session_id: 0,
},
};
TEEC_CloseSession(&mut session);
assert_eq!(session.imp.session_id, 0);
}
#[test]
fn test_finalize_context_null() {
TEEC_FinalizeContext(ptr::null_mut());
}
#[test]
fn test_finalize_context_uninitialized() {
let mut ctx = raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: -1,
reg_mem: false,
memref_null: false,
},
};
TEEC_FinalizeContext(&mut ctx);
}
#[test]
fn test_allocate_shared_memory_null_args() {
let res = TEEC_AllocateSharedMemory(ptr::null_mut(), ptr::null_mut());
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_allocate_shared_memory_zero_size() {
let mut ctx = raw::TEEC_Context {
imp: raw::TEEC_Context__Imp {
fd: -1,
reg_mem: false,
memref_null: false,
},
};
let mut shm = raw::TEEC_SharedMemory {
buffer: ptr::null_mut(),
size: 0,
flags: raw::TEEC_MEM_INPUT,
imp: raw::TEEC_SharedMemory__Imp {
id: -1,
alloced_size: 0,
shadow_buffer: ptr::null_mut(),
registered_fd: -1,
flags: 0,
},
};
let res = TEEC_AllocateSharedMemory(&mut ctx, &mut shm);
assert_eq!(res, raw::TEEC_ERROR_BAD_PARAMETERS);
}
#[test]
fn test_release_shared_memory_null() {
TEEC_ReleaseSharedMemory(ptr::null_mut());
}
#[test]
fn test_release_shared_memory_unregistered() {
let mut shm = raw::TEEC_SharedMemory {
buffer: ptr::null_mut(),
size: 0,
flags: 0,
imp: raw::TEEC_SharedMemory__Imp {
id: -1,
alloced_size: 0,
shadow_buffer: ptr::null_mut(),
registered_fd: -1,
flags: 0,
},
};
TEEC_ReleaseSharedMemory(&mut shm);
}
}