use rust_utee::{
api::tee_api_objects::{
TEE_AllocatePersistentObjectEnumerator, TEE_AllocateTransientObject,
TEE_CloseAndDeletePersistentObject, TEE_CloseObject, TEE_CreatePersistentObject,
TEE_FreePersistentObjectEnumerator, TEE_GenerateKey, TEE_GetNextPersistentObject,
TEE_GetObjectBufferAttribute, TEE_GetObjectInfo1, TEE_OpenPersistentObject,
TEE_ReadObjectData, TEE_ResetPersistentObjectEnumerator, TEE_RestrictObjectUsage1,
TEE_SeekObjectData, TEE_StartPersistentObjectEnumerator, TEE_TruncateObjectData,
TEE_USAGE_DEFAULT, TEE_WriteObjectData,
},
tee_api_defines::{
TEE_ATTR_ECC_PRIVATE_VALUE, TEE_ATTR_ECC_PUBLIC_VALUE_X, TEE_ATTR_ECC_PUBLIC_VALUE_Y,
TEE_ATTR_SECRET_VALUE, TEE_DATA_FLAG_ACCESS_READ, TEE_DATA_FLAG_ACCESS_WRITE,
TEE_DATA_FLAG_ACCESS_WRITE_META, TEE_DATA_FLAG_OVERWRITE, TEE_DATA_FLAG_SHARE_READ,
TEE_DATA_FLAG_SHARE_WRITE, TEE_ERROR_ITEM_NOT_FOUND, TEE_STORAGE_PRIVATE, TEE_SUCCESS,
TEE_TYPE_SM2_DSA_KEYPAIR, TEE_TYPE_SM2_PKE_KEYPAIR, TEE_TYPE_SM4, TEE_USAGE_EXTRACTABLE,
},
tee_api_types::{TEE_ObjectEnumHandle, TEE_ObjectHandle, TEE_ObjectInfo, TEE_Whence},
};
use rand::Rng;
use mbedtls::{
bignum::Mpi,
ecp::{EcGroup, EcPoint},
pk::{EcGroupId, Pk, Type},
rng::RngCallback,
};
use mbedtls_sys_auto::{
MD_SM3,
types::{
raw_types::{c_int, c_uchar, c_void},
size_t,
},
};
use rand_chacha::{
ChaCha20Rng,
rand_core::{RngCore, SeedableRng},
};
pub struct TeeSoftwareRng {
rng: ChaCha20Rng,
}
impl TeeSoftwareRng {
pub fn new() -> Self {
Self {
rng: ChaCha20Rng::seed_from_u64(rand::rng().random_range(0..u64::MAX)),
}
}
}
impl RngCallback for TeeSoftwareRng {
unsafe extern "C" fn call(p_rng: *mut c_void, data: *mut c_uchar, len: size_t) -> c_int {
let rng = unsafe { &mut *(p_rng as *mut TeeSoftwareRng) };
rng.rng
.fill_bytes(unsafe { core::slice::from_raw_parts_mut(data, len) });
0
}
fn data_ptr(&self) -> *mut c_void {
self as *const _ as *mut _
}
}
type TestResult = Result<(), ()>;
fn main() {
let args: Vec<String> = std::env::args().collect();
let obj_jd = "test_create_storage_object";
let data = b"test data for storage object";
let mut read_data = vec![0u8; data.len()];
if args.len() > 1 {
match args[1].as_str() {
"-c" => {
if let Err(_) = test_create_storage_object(obj_jd, data) {
eprintln!("test_create_storage_object failed");
std::process::exit(1);
}
}
"-r" => {
if let Err(_) = test_read_storage_object(obj_jd, &mut read_data) {
eprintln!("test_read_storage_object failed");
std::process::exit(1);
}
}
_ => {
eprintln!(
"Unknown argument: {}. Use -c for test_create_storage_object or -r for test_read_storage_object",
args[1]
);
std::process::exit(1);
}
}
} else {
test_all();
}
}
fn test_create_storage_object(obj_jd: &str, data: &[u8]) -> TestResult {
println!("test_create_storage_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_ACCESS_WRITE |
TEE_DATA_FLAG_ACCESS_WRITE_META |
TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
println!(
"create_storage_object result: {:#010x}, obj: {}",
res, object as usize
);
println!(
"write_storage_object data: {:?}",
String::from_utf8_lossy(data)
);
let res = TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
println!("write_object_data result: {:#010x}", res);
TEE_CloseObject(object);
#[allow(unreachable_code)]
Ok(())
}
fn test_read_storage_object(obj_jd: &str, read_data: &mut [u8]) -> TestResult {
println!("test_read_storage_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_data_flag =
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META;
let _ = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_data_flag,
&mut object,
);
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
read_data.len(),
&mut read_data_len,
);
println!("read_storage_object result: {:#010x}", res);
println!(
"read_storage_object data: {:?}",
String::from_utf8_lossy(read_data)
);
TEE_CloseObject(object);
Ok(())
}
fn test_all() {
let funcs: Vec<fn() -> TestResult> = vec![
test_create_raw_object,
test_obj_basic_operations,
test_create_object_with_initial_data,
test_create_object_without_overwrite,
test_create_object_with_overwrite,
test_open_nonexistent_object,
test_open_object_different_flags,
test_write_data_append,
test_write_data_large,
test_read_data_partial,
test_read_data_beyond_end,
test_seek_set,
test_seek_cur,
test_seek_end,
test_seek_boundary,
test_truncate_to_zero,
test_truncate_to_middle,
test_truncate_to_end,
test_delete_object,
test_get_sm2_dsa_keypair_attributes,
test_create_open_del_object,
test_generate_persistant_sm2_dsa_keypair,
test_create_two_objects,
test_enum_single_object,
test_create_some_objects,
test_create_open_read_some_objects,
test_enum_objects,
test_generate_key,
test_generate_sm4_key,
];
for func in &funcs {
let res = func();
if res.is_ok() {
println!("<<< test success");
} else {
eprintln!("<<< test failed");
}
}
let mut rng = rand::rng();
for i in 0..200 {
println!(">>>>>> storage_test with loop index: {}", i);
let idx = rng.random_range(0..funcs.len());
let func = &funcs[idx];
let res = func();
if res.is_ok() {
println!("<<< test success");
} else {
eprintln!("<<< test failed");
}
}
}
fn test_create_open_del_object() -> TestResult {
println!("test_create_open_del_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let create_flags = TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_ACCESS_WRITE |
TEE_DATA_FLAG_ACCESS_WRITE_META |
TEE_DATA_FLAG_OVERWRITE;
let open_flags =
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META;
let obj_id = "test_create_open_del_object";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
create_flags,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
open_flags,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_create_raw_object() -> TestResult {
println!("test_create_raw_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_ACCESS_WRITE |
TEE_DATA_FLAG_ACCESS_WRITE_META |
TEE_DATA_FLAG_OVERWRITE;
let obj_jd = "test_create_rawtest_object_create_object";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
println!(
"create_raw_object result: {:#010x}, obj: {}",
res, object as usize
);
let data = b"test_write_object_data";
let res = TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
println!("write_object_data result: {:#010x}", res);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
println!("seek_object_data result: {:#010x}", res);
let mut read_data = vec![0u8; data.len()];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data.len(),
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, data.len());
assert_eq!(read_data, data);
println!("read_object_data result: {:#010x}", res);
println!(
"read_object_data data: {:?}",
String::from_utf8_lossy(&read_data)
);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_obj_basic_operations() -> TestResult {
println!("test_obj_basic_operations");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ |
TEE_DATA_FLAG_ACCESS_WRITE |
TEE_DATA_FLAG_ACCESS_WRITE_META |
TEE_DATA_FLAG_OVERWRITE;
let obj_jd = "test_create_rawtest_object_create_object";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
println!(
"create_raw_object result: {:#010x}, obj: {}",
res, object as usize
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
let data = b"test_write_object_data";
let res = TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
println!("write_object_data result: {:#010x}", res);
assert_eq!(res, TEE_SUCCESS);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
println!("seek_object_data result: {:#010x}", res);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; data.len()];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data.len(),
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, data.len());
assert_eq!(read_data, data);
println!("read_object_data result: {:#010x}", res);
println!(
"read_object_data data: {:?}",
String::from_utf8_lossy(&read_data)
);
TEE_CloseObject(object);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
assert_eq!(res, TEE_ERROR_ITEM_NOT_FOUND);
println!("seek_object_data result: {:#010x}", res);
let obj_read_delete_flag =
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META;
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_read_delete_flag,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
println!(
"open_object result: {:#010x}, object: {}",
res, object as usize
);
let mut read_data = vec![0u8; data.len()];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data.len(),
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, data.len());
assert_eq!(read_data, data);
println!(
"read_object_data result: {:#010x}, data: {:?}",
res,
String::from_utf8_lossy(&read_data)
);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_read_delete_flag,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
println!(
"open_object result: {:#010x}, object: {}",
res, object as usize
);
let res = TEE_TruncateObjectData(object, 8);
assert_eq!(res, TEE_SUCCESS);
println!("truncate_object_data result: {:#010x}", res);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_jd.as_ptr() as *const _,
obj_jd.len() as usize,
obj_read_delete_flag,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
println!(
"open_object result: {:#010x}, object: {}",
res, object as usize
);
let mut read_data = vec![0u8; 8];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
8,
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, 8);
assert_eq!(read_data, &data[..8]);
println!(
"read_object_data result: {:#010x}, data: {:?}",
res,
String::from_utf8_lossy(&read_data)
);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_create_object_with_initial_data() -> TestResult {
println!(">>> test_create_object_with_initial_data");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_create_with_init_data";
let initial_data = b"initial_data_content";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
initial_data.as_ptr() as *const _,
initial_data.len(),
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
let mut read_data = vec![0u8; initial_data.len()];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
initial_data.len(),
&mut read_data_len,
);
println!(
"read_object_data result: {:#010x}, data_len: {}, data: {:?}",
res,
read_data_len,
String::from_utf8_lossy(&read_data)
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, initial_data.len());
assert_eq!(read_data, initial_data);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_create_object_without_overwrite() -> TestResult {
println!(">>> test_create_object_without_overwrite");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_create_without_overwrite";
let obj_data_flag =
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_ne!(res, TEE_SUCCESS);
println!(
"create without overwrite (second time) result: {:#010x}",
res
);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
if res == TEE_SUCCESS {
TEE_CloseAndDeletePersistentObject(object);
}
Ok(())
}
fn test_create_object_with_overwrite() -> TestResult {
println!(">>> test_create_object_with_overwrite");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_create_with_overwrite";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data1 = b"first_data";
let res = TEE_WriteObjectData(object, data1.as_ptr() as *const _, data1.len());
println!("write_object_data result: {:#010x}", res);
TEE_CloseObject(object);
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data2 = b"second_data";
TEE_WriteObjectData(object, data2.as_ptr() as *const _, data2.len());
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE_META, &mut object,
);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; data2.len()];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data2.len(),
&mut read_data_len,
);
assert_eq!(read_data, data2);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_open_nonexistent_object() -> TestResult {
println!(">>> test_open_nonexistent_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_nonexistent_object_12345";
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ,
&mut object,
);
assert_eq!(res, TEE_ERROR_ITEM_NOT_FOUND);
assert!(object.is_null());
Ok(())
}
fn test_open_object_different_flags() -> TestResult {
println!(">>> test_open_object_different_flags");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_open_different_flags";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_write_data_append() -> TestResult {
println!(">>> test_write_data_append");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_write_append";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data1 = b"first_part_";
let res = TEE_WriteObjectData(object, data1.as_ptr() as *const _, data1.len());
assert_eq!(res, TEE_SUCCESS);
let data2 = b"second_part";
let res = TEE_WriteObjectData(object, data2.as_ptr() as *const _, data2.len());
assert_eq!(res, TEE_SUCCESS);
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let total_len = data1.len() + data2.len();
let mut read_data = vec![0u8; total_len];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
total_len,
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, total_len);
assert_eq!(&read_data[..data1.len()], data1);
assert_eq!(&read_data[data1.len()..], data2);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_write_data_large() -> TestResult {
println!(">>> test_write_data_large");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_write_large";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let large_data: Vec<u8> = (0..1024).map(|i| (i % 256) as u8).collect();
let res = TEE_WriteObjectData(object, large_data.as_ptr() as *const _, large_data.len());
assert_eq!(res, TEE_SUCCESS);
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; large_data.len()];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
large_data.len(),
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, large_data.len());
assert_eq!(read_data, large_data);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_read_data_partial() -> TestResult {
println!(">>> test_read_data_partial");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_read_partial";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"abcdefghijklmnopqrstuvwxyz";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; 10];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
10,
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, 10);
assert_eq!(&read_data[..10], &data[..10]);
TEE_SeekObjectData(object, 10, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; 5];
let mut read_data_len = 0;
let res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
5,
&mut read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(read_data_len, 5);
assert_eq!(&read_data[..5], &data[10..15]);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_read_data_beyond_end() -> TestResult {
println!(">>> test_read_data_beyond_end");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_read_beyond_end";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"test_data";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; data.len() + 100];
let mut read_data_len = 0;
let _res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data.len() + 100,
&mut read_data_len,
);
assert_eq!(read_data_len, data.len());
assert_eq!(&read_data[..data.len()], data);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_seek_set() -> TestResult {
println!(">>> test_seek_set");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_seek_set";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"0123456789abcdef";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
let res = TEE_SeekObjectData(object, 5, TEE_Whence::TEE_DATA_SEEK_SET);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; 5];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
5,
&mut read_data_len,
);
assert_eq!(read_data_len, 5);
assert_eq!(&read_data[..5], &data[5..10]);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_seek_cur() -> TestResult {
println!(">>> test_seek_cur");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_seek_cur";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"0123456789abcdef";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; 5];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
5,
&mut read_data_len,
);
let res = TEE_SeekObjectData(object, 3, TEE_Whence::TEE_DATA_SEEK_CUR);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; 5];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
5,
&mut read_data_len,
);
assert_eq!(read_data_len, 5);
assert_eq!(&read_data[..5], &data[8..13]);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_seek_end() -> TestResult {
println!(">>> test_seek_end");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_seek_end";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"0123456789abcdef";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
let res = TEE_SeekObjectData(object, -5, TEE_Whence::TEE_DATA_SEEK_END);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; 5];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
5,
&mut read_data_len,
);
assert_eq!(read_data_len, 5);
assert_eq!(&read_data[..5], &data[data.len() - 5..]);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_seek_boundary() -> TestResult {
println!(">>> test_seek_boundary");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_seek_boundary";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"test_data";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
assert_eq!(res, TEE_SUCCESS);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_END);
assert_eq!(res, TEE_SUCCESS);
let mut read_data = vec![0u8; 10];
let mut read_data_len = 0;
let _res = TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
10,
&mut read_data_len,
);
assert_eq!(read_data_len, 0);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_truncate_to_zero() -> TestResult {
println!(">>> test_truncate_to_zero");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_truncate_to_zero";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"test_data_to_truncate";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
let res = TEE_TruncateObjectData(object, 0);
assert_eq!(res, TEE_SUCCESS);
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; 100];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
100,
&mut read_data_len,
);
assert_eq!(read_data_len, 0);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_truncate_to_middle() -> TestResult {
println!(">>> test_truncate_to_middle");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_truncate_middle";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"abcdefghijklmnop";
TEE_WriteObjectData(object, data.as_ptr() as *const _, data.len());
let truncate_size = 8;
let res = TEE_TruncateObjectData(object, truncate_size);
assert_eq!(res, TEE_SUCCESS);
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; truncate_size];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
truncate_size,
&mut read_data_len,
);
assert_eq!(read_data_len, truncate_size);
assert_eq!(&read_data[..truncate_size], &data[..truncate_size]);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_truncate_to_end() -> TestResult {
println!(">>> test_truncate_to_end");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_truncate_to_end";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
let data = b"test_data";
let data_len = data.len();
TEE_WriteObjectData(object, data.as_ptr() as *const _, data_len);
let res = TEE_TruncateObjectData(object, data_len);
assert_eq!(res, TEE_SUCCESS);
TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
let mut read_data = vec![0u8; data_len];
let mut read_data_len = 0;
TEE_ReadObjectData(
object,
read_data.as_mut_ptr() as *mut _,
data_len,
&mut read_data_len,
);
assert_eq!(read_data_len, data_len);
assert_eq!(read_data, data);
TEE_CloseAndDeletePersistentObject(object);
Ok(())
}
fn test_delete_object() -> TestResult {
println!(">>> test_delete_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = "test_delete_object";
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE;
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
core::ptr::null_mut(),
core::ptr::null(),
0,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseAndDeletePersistentObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ,
&mut object,
);
assert_eq!(res, TEE_ERROR_ITEM_NOT_FOUND);
Ok(())
}
fn test_get_sm2_dsa_keypair_attributes() -> TestResult {
println!(">>> test_alloc_transient_object");
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let res = TEE_AllocateTransientObject(TEE_TYPE_SM2_DSA_KEYPAIR, 256, &mut object);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
let res = TEE_GenerateKey(object, 256, core::ptr::null(), 0);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
let mut private_key = vec![0u8; 32];
let mut private_key_len = private_key.len() as usize;
let res = TEE_GetObjectBufferAttribute(
object,
TEE_ATTR_ECC_PRIVATE_VALUE,
private_key.as_mut_ptr() as *mut _,
&mut private_key_len,
);
println!(
"SM2 DSA get private_key result: {:#010x}, private_key: {:?}, private_key_len: {}",
res,
hex::encode(private_key),
private_key_len
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(private_key_len, 31 | 32));
let mut public_key_x = vec![0u8; 32];
let mut public_key_x_len = public_key_x.len() as usize;
let res = TEE_GetObjectBufferAttribute(
object,
TEE_ATTR_ECC_PUBLIC_VALUE_X,
public_key_x.as_mut_ptr() as *mut _,
&mut public_key_x_len,
);
println!(
"SM2 DSA get public_key_x result: {:#010x}, public_key_x: {:?}, public_key_x_len: {}",
res,
hex::encode(public_key_x),
public_key_x_len
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(public_key_x_len, 31 | 32));
let mut public_key_y = vec![0u8; 32];
let mut public_key_y_len = public_key_y.len() as usize;
let res = TEE_GetObjectBufferAttribute(
object,
TEE_ATTR_ECC_PUBLIC_VALUE_Y,
public_key_y.as_mut_ptr() as *mut _,
&mut public_key_y_len,
);
println!(
"SM2 DSA get public_key_y result: {:#010x}, public_key_y: {:?}, public_key_y_len: {}",
res,
hex::encode(public_key_y),
public_key_y_len
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(public_key_y_len, 31 | 32));
let mut object_info = TEE_ObjectInfo::default();
let res = TEE_GetObjectInfo1(object, &mut object_info);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(object_info.objectType, TEE_TYPE_SM2_DSA_KEYPAIR as u32);
assert_eq!(object_info.objectUsage, TEE_USAGE_DEFAULT as u32);
println!(
"SM2 DSA get object info result: {:#010x}, object_info: {:#010X?}",
res, object_info
);
let restrict_usage = object_info.objectUsage & !TEE_USAGE_EXTRACTABLE;
let res = TEE_RestrictObjectUsage1(object, restrict_usage);
assert_eq!(res, TEE_SUCCESS);
let res = TEE_GetObjectInfo1(object, &mut object_info);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(object_info.objectUsage, restrict_usage);
let mut public_key_x = vec![0u8; 32];
let mut public_key_x_len = public_key_x.len() as usize;
let res = TEE_GetObjectBufferAttribute(
object,
TEE_ATTR_ECC_PUBLIC_VALUE_X,
public_key_x.as_mut_ptr() as *mut _,
&mut public_key_x_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(public_key_x_len, 31 | 32));
TEE_CloseObject(object);
Ok(())
}
fn test_generate_persistant_sm2_dsa_keypair() -> TestResult {
println!(">>> test_generate_persistant_sm2_dsa_keypair");
let mut derive_key: TEE_ObjectHandle = core::ptr::null_mut();
let res = TEE_AllocateTransientObject(TEE_TYPE_SM2_DSA_KEYPAIR, 256, &mut derive_key);
assert_eq!(res, TEE_SUCCESS);
assert!(!derive_key.is_null());
let res = TEE_GenerateKey(derive_key, 256, core::ptr::null(), 0);
assert_eq!(res, TEE_SUCCESS);
assert!(!derive_key.is_null());
let obj_data_flag = TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_SHARE_READ
| TEE_DATA_FLAG_SHARE_WRITE
| TEE_DATA_FLAG_OVERWRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META;
let obj_id = "test_generate_persistant_sm2_dsa_keypair";
let mut key_object: TEE_ObjectHandle = core::ptr::null_mut();
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag,
derive_key,
core::ptr::null(),
0,
&mut key_object,
);
assert_eq!(res, TEE_SUCCESS);
TEE_CloseObject(derive_key);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
obj_data_flag & !TEE_DATA_FLAG_OVERWRITE,
&mut key_object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!key_object.is_null());
println!(
"TEE_OpenPersistentObject res: {:#010X?}, key_object: {:#010X?}",
res, key_object
);
let mut public_key_x = vec![0u8; 32];
let mut public_key_x_len = public_key_x.len() as usize;
let res = TEE_GetObjectBufferAttribute(
key_object,
TEE_ATTR_ECC_PUBLIC_VALUE_X,
public_key_x.as_mut_ptr() as *mut _,
&mut public_key_x_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(public_key_x_len, 31 | 32));
TEE_CloseAndDeletePersistentObject(key_object);
Ok(())
}
fn test_enum_single_object() -> TestResult {
println!("test_enum_single_object");
let mut object1: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id1 = "test_enum_2_object_object1";
let obj_data1 = b"object1_data";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id1.as_ptr() as *const _,
obj_id1.len() as usize,
TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_ACCESS_WRITE_META,
core::ptr::null_mut(),
obj_data1.as_ptr() as *const _,
obj_data1.len() as usize,
&mut object1,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object1.is_null());
TEE_CloseAndDeletePersistentObject(object1);
Ok(())
}
fn test_create_two_objects() -> TestResult {
println!("test_create_two_objects");
let mut object1: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id1 = "test_enum_2_object_object1";
let obj_data1 = b"object1_data";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id1.as_ptr() as *const _,
obj_id1.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE,
core::ptr::null_mut(),
obj_data1.as_ptr() as *const _,
obj_data1.len() as usize,
&mut object1,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object1.is_null());
let mut object2: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id2 = "test_enum_2_object_object2";
let obj_data2 = b"object2_data";
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id2.as_ptr() as *const _,
obj_id2.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE,
core::ptr::null_mut(),
obj_data2.as_ptr() as *const _,
obj_data2.len() as usize,
&mut object2,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object2.is_null());
TEE_CloseAndDeletePersistentObject(object1);
TEE_CloseAndDeletePersistentObject(object2);
Ok(())
}
fn test_create_some_objects() -> TestResult {
println!("test_create_some_objects");
for file_idx in 0..10 {
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = format!("test_create_some_objects_object_{}", file_idx);
let mut obj_data = vec![0u8; rand::rng().random_range(1..4096)];
for i in 0..obj_data.len() {
obj_data[i] = rand::rng().random_range(0..256) as u8;
}
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE,
core::ptr::null_mut(),
obj_data.as_ptr() as *const _,
obj_data.len() as usize,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
TEE_CloseAndDeletePersistentObject(object);
}
Ok(())
}
fn test_create_open_read_some_objects() -> TestResult {
println!("test_create_open_read_some_objects");
for file_idx in 0..10 {
println!("test_create_open_read_some_objects_file_idx: {}", file_idx);
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = format!("test_create_open_read_some_objects_{}", file_idx);
let mut obj_create_data = vec![0u8; rand::rng().random_range(1..4096)];
for i in 0..obj_create_data.len() {
obj_create_data[i] = rand::rng().random_range(0..256) as u8;
}
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE,
core::ptr::null_mut(),
obj_create_data.as_ptr() as *const _,
obj_create_data.len() as usize,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
TEE_CloseObject(object);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
let mut obj_read_data = vec![0u8; obj_create_data.len()];
let mut obj_read_data_len = 0;
let res = TEE_ReadObjectData(
object,
obj_read_data.as_mut_ptr() as *mut _,
obj_create_data.len(),
&mut obj_read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(obj_read_data_len, obj_create_data.len());
assert_eq!(obj_read_data, obj_create_data);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_END);
assert_eq!(res, TEE_SUCCESS);
let mut obj_write_data = vec![0u8; rand::rng().random_range(1..512)];
for i in 0..obj_write_data.len() {
obj_write_data[i] = rand::rng().random_range(0..256) as u8;
}
let res = TEE_WriteObjectData(
object,
obj_write_data.as_ptr() as *const _,
obj_write_data.len(),
);
assert_eq!(res, TEE_SUCCESS);
let res = TEE_SeekObjectData(object, 0, TEE_Whence::TEE_DATA_SEEK_SET);
assert_eq!(res, TEE_SUCCESS);
let mut obj_read_data = vec![0u8; obj_create_data.len() + obj_write_data.len()];
let mut obj_read_data_len = 0;
let res = TEE_ReadObjectData(
object,
obj_read_data.as_mut_ptr() as *mut _,
obj_read_data.len(),
&mut obj_read_data_len,
);
assert_eq!(res, TEE_SUCCESS);
assert_eq!(
obj_read_data_len,
obj_create_data.len() + obj_write_data.len()
);
assert_eq!(
obj_read_data,
[&obj_create_data[..], &obj_write_data[..]].concat()
);
TEE_CloseAndDeletePersistentObject(object);
}
Ok(())
}
fn test_enum_objects() -> TestResult {
println!("test_enum_objects");
let num_objs = 10;
debug_assert!(num_objs >= 2);
for file_idx in 0..num_objs {
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = format!("test_enum_objects_object_{}", file_idx);
let obj_data = format!("object_data_{}", file_idx);
let res = TEE_CreatePersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_READ
| TEE_DATA_FLAG_ACCESS_WRITE
| TEE_DATA_FLAG_ACCESS_WRITE_META
| TEE_DATA_FLAG_OVERWRITE,
core::ptr::null_mut(),
obj_data.as_ptr() as *const _,
obj_data.len() as usize,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
TEE_CloseObject(object);
}
let mut object_enum: TEE_ObjectEnumHandle = core::ptr::null_mut();
let res = TEE_AllocatePersistentObjectEnumerator(&mut object_enum);
assert_eq!(res, TEE_SUCCESS);
let res = TEE_StartPersistentObjectEnumerator(object_enum, TEE_STORAGE_PRIVATE);
assert_eq!(res, TEE_SUCCESS);
let mut restarted_flag = false;
for i in 0.. {
println!("get the next object with index: {}", i);
let mut object_info: TEE_ObjectInfo = TEE_ObjectInfo::default();
let mut object_id = vec![0u8; 1024];
let mut object_id_len = object_id.len();
let res = TEE_GetNextPersistentObject(
object_enum,
&mut object_info,
object_id.as_mut_ptr() as *mut _,
&mut object_id_len,
);
if res == TEE_ERROR_ITEM_NOT_FOUND {
println!(
"no more objects, return value: {:#010X?}, break the loop",
res
);
break;
}
if res != TEE_SUCCESS {
panic!(
"get next object failed, return value: {:#010X?}, break the loop",
res
);
}
if !restarted_flag && i == num_objs / 2 {
restarted_flag = true;
if rand::rng().random_range(0..2) == 0 {
println!("restart the object enumerator");
TEE_ResetPersistentObjectEnumerator(object_enum);
TEE_StartPersistentObjectEnumerator(object_enum, TEE_STORAGE_PRIVATE);
}
}
}
TEE_FreePersistentObjectEnumerator(object_enum);
for file_idx in 0..num_objs {
let mut object: TEE_ObjectHandle = core::ptr::null_mut();
let obj_id = format!("test_enum_objects_object_{}", file_idx);
let res = TEE_OpenPersistentObject(
TEE_STORAGE_PRIVATE,
obj_id.as_ptr() as *const _,
obj_id.len() as usize,
TEE_DATA_FLAG_ACCESS_WRITE_META,
&mut object,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!object.is_null());
TEE_CloseAndDeletePersistentObject(object);
}
Ok(())
}
#[allow(dead_code)]
const SM2_PUBKEY_LEN: usize = 64;
#[allow(dead_code)]
const SM2_PRIKEY_LEN: usize = 32;
const SM2_KEY_SIZE: usize = SM2_PRIKEY_LEN * 8;
fn test_generate_key() -> TestResult {
println!("test_generate_key");
let mut transient_key: TEE_ObjectHandle = core::ptr::null_mut();
let res = TEE_AllocateTransientObject(
TEE_TYPE_SM2_PKE_KEYPAIR,
SM2_KEY_SIZE as u32,
&mut transient_key,
);
assert_eq!(res, TEE_SUCCESS);
assert!(!transient_key.is_null());
let res = TEE_GenerateKey(transient_key, SM2_KEY_SIZE as u32, core::ptr::null(), 0);
assert_eq!(res, TEE_SUCCESS);
assert!(!transient_key.is_null());
let mut pubkey_x = vec![0u8; SM2_PUBKEY_LEN / 2];
let mut pubkey_y = vec![0u8; SM2_PUBKEY_LEN / 2];
let mut pubkey_x_len = pubkey_x.len() as usize;
let mut pubkey_y_len = pubkey_y.len() as usize;
let res = TEE_GetObjectBufferAttribute(
transient_key,
TEE_ATTR_ECC_PUBLIC_VALUE_X,
pubkey_x.as_mut_ptr() as *mut _,
&mut pubkey_x_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(pubkey_x_len, 31 | 32));
if pubkey_x_len == 31 {
pubkey_x.copy_within(0..31, 1);
pubkey_x[0] = 0x00;
}
let res = TEE_GetObjectBufferAttribute(
transient_key,
TEE_ATTR_ECC_PUBLIC_VALUE_Y,
pubkey_y.as_mut_ptr() as *mut _,
&mut pubkey_y_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(pubkey_y_len, 31 | 32));
if pubkey_y_len == 31 {
pubkey_y.copy_within(0..31, 1);
pubkey_y[0] = 0x00;
}
println!("pubkey_x: {:?}", hex::encode(&pubkey_x));
println!("pubkey_y: {:?}", hex::encode(&pubkey_y));
let mut private_key = vec![0u8; SM2_PRIKEY_LEN];
let mut private_key_len = private_key.len() as usize;
let res = TEE_GetObjectBufferAttribute(
transient_key,
TEE_ATTR_ECC_PRIVATE_VALUE,
private_key.as_mut_ptr() as *mut _,
&mut private_key_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(private_key_len, 31 | 32));
if private_key_len == 31 {
private_key.copy_within(0..31, 1);
private_key[0] = 0x00;
}
println!("private_key: {:?}", hex::encode(&private_key));
check_sm2_keypair(&pubkey_x, &pubkey_y, &private_key).unwrap();
TEE_CloseObject(transient_key);
Ok(())
}
fn check_sm2_keypair(pubkey_x: &[u8], pubkey_y: &[u8], private_key: &[u8]) -> TestResult {
let mpi_x = Mpi::from_binary(pubkey_x).unwrap();
let mpi_y = Mpi::from_binary(pubkey_y).unwrap();
let mpi_private = Mpi::from_binary(private_key).unwrap();
let pub_point = EcPoint::from_components(mpi_x, mpi_y).unwrap();
let curve = EcGroup::new(EcGroupId::SM2P256R1).unwrap();
let mut private_key =
Pk::private_from_ec_components_extend(curve.clone(), mpi_private, Type::SM2.into())
.unwrap();
let mut pub_key =
Pk::public_from_ec_components_extend(curve, pub_point, Type::SM2.into()).unwrap();
let plain = b"ENCRYPT TEST ENCRYPT TEST ENCRYP";
let mut cipher = [0u8; 32 + 97];
let mut decrypted = [0u8; 32];
let mut rng = TeeSoftwareRng::new();
let _ = pub_key.encrypt_extend(plain, &mut cipher, &mut rng, Some(MD_SM3));
let _ = private_key.decrypt_extend(&cipher, &mut decrypted, &mut rng, Some(MD_SM3));
assert_eq!(&decrypted, plain);
Ok(())
}
fn test_generate_sm4_key() -> TestResult {
println!("test_generate_sm4_key");
let mut transient_key: TEE_ObjectHandle = core::ptr::null_mut();
let res = TEE_AllocateTransientObject(TEE_TYPE_SM4, 128, &mut transient_key);
assert_eq!(res, TEE_SUCCESS);
assert!(!transient_key.is_null());
let res = TEE_GenerateKey(transient_key, 128, core::ptr::null(), 0);
assert_eq!(res, TEE_SUCCESS);
assert!(!transient_key.is_null());
let mut key = vec![0u8; 16];
let mut key_len = key.len() as usize;
let res = TEE_GetObjectBufferAttribute(
transient_key,
TEE_ATTR_SECRET_VALUE,
key.as_mut_ptr() as *mut _,
&mut key_len,
);
assert_eq!(res, TEE_SUCCESS);
assert!(matches!(key_len, 16));
println!("key: {:?}", hex::encode(&key));
assert!(!key.iter().all(|x| *x == 0x00));
TEE_CloseObject(transient_key);
Ok(())
}