1#![allow(non_camel_case_types)]
11
12use std::{
13 ffi::c_void,
14 io::{Error, ErrorKind},
15 mem, ptr,
16};
17
18use num_enum::{FromPrimitive, IntoPrimitive};
19use uuid::Uuid;
20
21use cc_teec::{
22 TEEC_AllocateSharedMemory, TEEC_CloseSession, TEEC_FinalizeContext, TEEC_InitializeContext,
23 TEEC_InvokeCommand, TEEC_OpenSession, TEEC_RegisterSharedMemory, TEEC_ReleaseSharedMemory, raw,
24};
25
26const EXAMPLE_TA_UUID: &str = "9b28392f-39d2-497d-91af-b6600e3d6a3e";
27
28#[derive(FromPrimitive, IntoPrimitive)]
29#[repr(u32)]
30pub enum Command {
31 ValueInputOutput = 0, ValueInout = 1, MemrefTempInputOutput = 10, MemrefTempInout = 11, MemrefWholeInputOutput = 20, MemrefWholeInout = 21, MemrefPartialInputOutput = 30, MemrefPartialInout = 31, MixedParams = 100,
49
50 #[default]
51 Unknown = 0xFF,
52}
53
54type Result<T> = std::result::Result<T, Error>;
55
56struct Client_Session {
60 ctx: Box<raw::TEEC_Context>,
65 session: raw::TEEC_Session,
67}
68
69impl Client_Session {
70 fn new(uuid: &raw::TEEC_UUID) -> Result<Self> {
71 let mut ctx: Box<raw::TEEC_Context> = Box::new(unsafe { mem::zeroed() });
74 let mut session: raw::TEEC_Session = unsafe { mem::zeroed() };
75 let mut origin = 0_u32;
76
77 let res = TEEC_InitializeContext(ptr::null(), ctx.as_mut());
78 if res != raw::TEEC_SUCCESS {
79 return Err(Error::from_raw_os_error(res as i32));
80 }
81
82 let res = TEEC_OpenSession(
83 ctx.as_mut(),
84 &mut session,
85 uuid,
86 raw::TEEC_LOGIN_PUBLIC,
87 ptr::null(),
88 ptr::null_mut(),
89 &mut origin,
90 );
91
92 if res != raw::TEEC_SUCCESS {
93 TEEC_FinalizeContext(ctx.as_mut());
94 return Err(Error::from_raw_os_error(res as i32));
95 }
96
97 Ok(Self { ctx, session })
98 }
99
100 fn invoke_command(&self, cmd_id: u32, op: &mut raw::TEEC_Operation) -> Result<()> {
101 let mut origin = 0_u32;
102 let res = TEEC_InvokeCommand(&self.session as *const _ as *mut _, cmd_id, op, &mut origin);
103
104 if res != raw::TEEC_SUCCESS {
105 return Err(Error::from_raw_os_error(res as i32));
106 }
107
108 Ok(())
109 }
110
111 fn context_mut(&mut self) -> &mut raw::TEEC_Context {
113 self.ctx.as_mut()
114 }
115}
116
117impl Drop for Client_Session {
118 fn drop(&mut self) {
119 TEEC_CloseSession(&mut self.session);
120 TEEC_FinalizeContext(self.ctx.as_mut());
121 }
122}
123
124fn main() -> Result<()> {
125 let uuid = Uuid::parse_str(EXAMPLE_TA_UUID)
126 .map_err(|_| Error::new(ErrorKind::InvalidInput, "无效 UUID"))?;
127 let teec_uuid = uuid_to_teec_uuid(&uuid)?;
128 let mut session = Client_Session::new(&teec_uuid)?;
129
130 value_types(&session)?;
131 memref_temp_types(&session)?;
132 memref_whole(&mut session)?;
133 memref_partial(&mut session)?;
134 mixed_params(&session)?;
135
136 Ok(())
137}
138
139fn value_types(session: &Client_Session) -> Result<()> {
141 println!("\nVALUE 参数类型");
142
143 {
145 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
147
148 op.paramTypes = raw::TEEC_PARAM_TYPES(
149 raw::TEEC_VALUE_INPUT,
150 raw::TEEC_VALUE_OUTPUT,
151 raw::TEEC_NONE,
152 raw::TEEC_NONE,
153 );
154 op.params[0].value.a = 100;
155 op.params[0].value.b = 200;
156
157 session.invoke_command(Command::ValueInputOutput.into(), &mut op)?;
158
159 let result = unsafe { op.params[1].value.a };
162 println!(" VALUE_INPUT+OUTPUT: {} + {} = {}", 100, 200, result);
163 }
164
165 {
167 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
169
170 op.paramTypes = raw::TEEC_PARAM_TYPES(
171 raw::TEEC_VALUE_INOUT,
172 raw::TEEC_NONE,
173 raw::TEEC_NONE,
174 raw::TEEC_NONE,
175 );
176 op.params[0].value.a = 42;
177 op.params[0].value.b = 99;
178
179 session.invoke_command(Command::ValueInout.into(), &mut op)?;
180
181 let a_out = unsafe { op.params[0].value.a };
184 let b_out = unsafe { op.params[0].value.b };
185 println!(" VALUE_INOUT: (42, 99) → ({}, {})", a_out, b_out);
186 }
187
188 Ok(())
189}
190
191fn memref_temp_types(session: &Client_Session) -> Result<()> {
193 println!("\nMEMREF TEMP 参数类型");
194
195 {
197 let input_data = vec![1u8, 2, 3, 4, 5];
198 let mut output_data = vec![0u8; 16];
199
200 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
202
203 op.paramTypes = raw::TEEC_PARAM_TYPES(
204 raw::TEEC_MEMREF_TEMP_INPUT,
205 raw::TEEC_MEMREF_TEMP_OUTPUT,
206 raw::TEEC_NONE,
207 raw::TEEC_NONE,
208 );
209 op.params[0].tmpref.buffer = input_data.as_ptr() as *mut _;
210 op.params[0].tmpref.size = input_data.len();
211 op.params[1].tmpref.buffer = output_data.as_mut_ptr() as *mut _;
212 op.params[1].tmpref.size = output_data.len();
213
214 session.invoke_command(Command::MemrefTempInputOutput.into(), &mut op)?;
215
216 println!(
217 " TEMP_INPUT+OUTPUT: {:?} → {:?}",
218 input_data,
219 &output_data[..8]
220 );
221 }
222
223 {
225 let mut inout_data: Vec<u8> = vec![0xAA, 0xBB, 0xCC, 0xDD];
226
227 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
229
230 op.paramTypes = raw::TEEC_PARAM_TYPES(
231 raw::TEEC_MEMREF_TEMP_INOUT,
232 raw::TEEC_NONE,
233 raw::TEEC_NONE,
234 raw::TEEC_NONE,
235 );
236 op.params[0].tmpref.buffer = inout_data.as_mut_ptr() as *mut _;
237 op.params[0].tmpref.size = inout_data.len();
238
239 session.invoke_command(Command::MemrefTempInout.into(), &mut op)?;
240 println!(
241 " TEMP_INOUT: {:?} → {:?}",
242 &[0xAA, 0xBB, 0xCC, 0xDD],
243 inout_data
244 );
245 }
246
247 Ok(())
248}
249
250fn memref_whole_input_output(session: &mut Client_Session) -> Result<()> {
252 let input_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
253 let output_size = 8;
254
255 let mut input_shm =
257 allocate_shared_memory(session.context_mut(), input_data.len(), raw::TEEC_MEM_INPUT)?;
258 copy_to_shm(&input_data, &input_shm);
259
260 let mut output_shm =
262 allocate_shared_memory(session.context_mut(), output_size, raw::TEEC_MEM_OUTPUT)?;
263
264 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
267 op.paramTypes = raw::TEEC_PARAM_TYPES(
268 raw::TEEC_MEMREF_WHOLE,
269 raw::TEEC_MEMREF_WHOLE,
270 raw::TEEC_NONE,
271 raw::TEEC_NONE,
272 );
273 op.params[0].memref.parent = &mut input_shm as *mut _;
274 op.params[0].memref.size = input_data.len();
275 op.params[1].memref.parent = &mut output_shm as *mut _;
276 op.params[1].memref.size = output_size;
277
278 session.invoke_command(Command::MemrefWholeInputOutput.into(), &mut op)?;
279
280 let output_data = read_from_shm(&output_shm, output_size);
281 println!(" WHOLE_INPUT+OUTPUT: {:?} → {:?}", input_data, output_data);
282
283 TEEC_ReleaseSharedMemory(&mut input_shm);
284 TEEC_ReleaseSharedMemory(&mut output_shm);
285
286 Ok(())
287}
288
289fn memref_whole_inout_allocated(session: &mut Client_Session) -> Result<()> {
291 let mut data = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
292 let original = data.clone();
293 let flags = raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT;
294 let mut shm = allocate_shared_memory(session.context_mut(), data.len(), flags)?;
295
296 copy_to_shm(&data, &shm);
297
298 let mut op = create_memref_operation(&mut shm, data.len());
299
300 session.invoke_command(Command::MemrefWholeInout.into(), &mut op)?;
301
302 copy_from_shm(&shm, &mut data);
303
304 println!(" WHOLE_INOUT (Alloc): {:?} → {:?}", original, data);
305
306 TEEC_ReleaseSharedMemory(&mut shm);
307
308 Ok(())
309}
310
311fn memref_whole_inout_registered(session: &mut Client_Session) -> Result<()> {
313 let mut data = vec![1u8, 2, 3, 4, 5, 6, 7, 8];
314 let original = data.clone();
315 let flags = raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT;
316
317 let mut shm = register_shared_memory(
319 session.context_mut(),
320 data.as_mut_ptr() as *mut c_void,
321 data.len(),
322 flags,
323 )?;
324
325 let mut op = create_memref_operation(&mut shm, data.len());
326 session.invoke_command(Command::MemrefWholeInout.into(), &mut op)?;
327
328 copy_from_shm(&shm, &mut data);
331
332 println!(" WHOLE_INOUT (Register): {:?} → {:?}", original, data);
333
334 TEEC_ReleaseSharedMemory(&mut shm);
335
336 Ok(())
337}
338
339fn memref_whole(session: &mut Client_Session) -> Result<()> {
340 println!("\nMEMREF WHOLE 参数类型");
341 memref_whole_input_output(session)?;
342 memref_whole_inout_allocated(session)?;
343 memref_whole_inout_registered(session)?;
344 Ok(())
345}
346
347fn allocate_shared_memory(
348 ctx: &mut raw::TEEC_Context,
349 size: usize,
350 flags: u32,
351) -> Result<raw::TEEC_SharedMemory> {
352 let mut shm: raw::TEEC_SharedMemory = unsafe { mem::zeroed() };
354 shm.size = size;
355 shm.flags = flags;
356
357 let res = TEEC_AllocateSharedMemory(ctx, &mut shm);
358 if res != raw::TEEC_SUCCESS {
359 return Err(Error::from_raw_os_error(res as i32));
360 }
361
362 Ok(shm)
363}
364
365fn register_shared_memory(
367 ctx: &mut raw::TEEC_Context,
368 buffer: *mut c_void,
369 size: usize,
370 flags: u32,
371) -> Result<raw::TEEC_SharedMemory> {
372 let mut shm: raw::TEEC_SharedMemory = unsafe { mem::zeroed() };
374 shm.buffer = buffer;
375 shm.size = size;
376 shm.flags = flags;
377
378 let res = TEEC_RegisterSharedMemory(ctx, &mut shm);
379 if res != raw::TEEC_SUCCESS {
380 return Err(Error::from_raw_os_error(res as i32));
381 }
382
383 Ok(shm)
384}
385
386fn copy_to_shm(data: &[u8], shm: &raw::TEEC_SharedMemory) {
388 unsafe {
393 ptr::copy_nonoverlapping(data.as_ptr(), shm.buffer as *mut u8, data.len());
394 }
395}
396
397fn copy_from_shm(shm: &raw::TEEC_SharedMemory, data: &mut [u8]) {
399 unsafe {
404 ptr::copy_nonoverlapping(shm.buffer as *const u8, data.as_mut_ptr(), data.len());
405 }
406}
407
408fn read_from_shm(shm: &raw::TEEC_SharedMemory, size: usize) -> Vec<u8> {
410 let mut data = vec![0u8; size];
411 unsafe {
416 ptr::copy_nonoverlapping(shm.buffer as *const u8, data.as_mut_ptr(), size);
417 }
418 data
419}
420
421fn read_from_shm_offset(shm: &raw::TEEC_SharedMemory, offset: usize, size: usize) -> Vec<u8> {
423 let mut data = vec![0u8; size];
424 unsafe {
429 ptr::copy_nonoverlapping(
430 (shm.buffer as *const u8).add(offset),
431 data.as_mut_ptr(),
432 size,
433 );
434 }
435 data
436}
437
438fn copy_to_shm_offset(data: &[u8], shm: &raw::TEEC_SharedMemory, offset: usize) {
440 unsafe {
445 ptr::copy_nonoverlapping(
446 data.as_ptr(),
447 (shm.buffer as *mut u8).add(offset),
448 data.len(),
449 );
450 }
451}
452
453fn create_memref_operation(shm: &mut raw::TEEC_SharedMemory, size: usize) -> raw::TEEC_Operation {
455 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
457 op.paramTypes = raw::TEEC_PARAM_TYPES(
458 raw::TEEC_MEMREF_WHOLE,
459 raw::TEEC_NONE,
460 raw::TEEC_NONE,
461 raw::TEEC_NONE,
462 );
463 op.params[0].memref.parent = shm;
464 op.params[0].memref.size = size;
465 op
466}
467
468fn memref_partial_input_output(
470 session: &mut Client_Session,
471 shm: &mut raw::TEEC_SharedMemory,
472 page_size: usize,
473) -> Result<()> {
474 let input_data = vec![0x10, 0x20, 0x30, 0x40];
475 let output_size = 8;
476 let input_offset = 0; let output_offset = page_size; copy_to_shm_offset(&input_data, shm, input_offset);
481
482 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
484 op.paramTypes = raw::TEEC_PARAM_TYPES(
485 raw::TEEC_MEMREF_PARTIAL_INPUT,
486 raw::TEEC_MEMREF_PARTIAL_OUTPUT,
487 raw::TEEC_NONE,
488 raw::TEEC_NONE,
489 );
490 op.params[0].memref.parent = shm;
492 op.params[0].memref.offset = input_offset;
493 op.params[0].memref.size = input_data.len();
494 op.params[1].memref.parent = shm;
496 op.params[1].memref.offset = output_offset;
497 op.params[1].memref.size = output_size;
498
499 session.invoke_command(Command::MemrefPartialInputOutput.into(), &mut op)?;
500
501 let output_data = read_from_shm_offset(shm, output_offset, output_size);
503 println!(
504 " PARTIAL_INPUT+OUTPUT:\toffset[0]={:?} → offset[{}]={:?}",
505 input_data, output_offset, output_data
506 );
507
508 Ok(())
509}
510
511fn memref_partial_inout(
513 session: &mut Client_Session,
514 shm: &mut raw::TEEC_SharedMemory,
515 page_size: usize,
516) -> Result<()> {
517 let data = vec![0x01, 0x02, 0x03, 0x04];
518 let key = 0x55u8;
519 let original = data.clone();
520
521 let offset = 2 * page_size; copy_to_shm_offset(&data, shm, offset);
525
526 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
528
529 op.paramTypes = raw::TEEC_PARAM_TYPES(
531 raw::TEEC_VALUE_INPUT,
532 raw::TEEC_MEMREF_PARTIAL_INOUT,
533 raw::TEEC_NONE,
534 raw::TEEC_NONE,
535 );
536 op.params[0].value.a = key as u32;
537 op.params[1].memref.parent = shm;
539 op.params[1].memref.offset = offset;
540 op.params[1].memref.size = data.len();
541
542 session.invoke_command(Command::MemrefPartialInout.into(), &mut op)?;
543
544 let result = read_from_shm_offset(shm, offset, data.len());
546 println!(
547 " PARTIAL_INOUT: offset[{}]={:?} ^ 0x{:02X} → {:?}",
548 offset, original, key, result
549 );
550
551 Ok(())
552}
553
554fn memref_partial(session: &mut Client_Session) -> Result<()> {
555 println!("\nMEMREF PARTIAL 参数类型");
556 let page_size = 4096;
563 let shm_size = 8 * page_size; let mut shm = allocate_shared_memory(
565 session.context_mut(),
566 shm_size,
567 raw::TEEC_MEM_INPUT | raw::TEEC_MEM_OUTPUT,
568 )?;
569
570 memref_partial_input_output(session, &mut shm, page_size)?;
571 memref_partial_inout(session, &mut shm, page_size)?;
572
573 TEEC_ReleaseSharedMemory(&mut shm);
574
575 Ok(())
576}
577
578fn mixed_params(session: &Client_Session) -> Result<()> {
580 println!("\n混合参数示例");
581 let input_data = vec![10u8, 20, 30, 40, 50];
582 let mut output_hash = vec![0u8; 4];
583
584 let mut op: raw::TEEC_Operation = unsafe { mem::zeroed() };
586 op.paramTypes = raw::TEEC_PARAM_TYPES(
587 raw::TEEC_VALUE_INOUT,
588 raw::TEEC_MEMREF_TEMP_INPUT,
589 raw::TEEC_MEMREF_TEMP_OUTPUT,
590 raw::TEEC_VALUE_OUTPUT,
591 );
592
593 op.params[0].value.a = 7; op.params[1].tmpref.buffer = input_data.as_ptr() as *mut _;
595 op.params[1].tmpref.size = input_data.len();
596 op.params[2].tmpref.buffer = output_hash.as_mut_ptr() as *mut _;
597 op.params[2].tmpref.size = output_hash.len();
598
599 session.invoke_command(Command::MixedParams.into(), &mut op)?;
600
601 let counter = unsafe { op.params[0].value.a };
602 let status = unsafe { op.params[3].value.a };
603 let processed = unsafe { op.params[3].value.b };
604
605 println!(" 输入: counter={}, data={:?}", 7, input_data);
606 println!(
607 " 输出: counter={}, hash=0x{:02X}{:02X}{:02X}{:02X}, status=0x{:08X}, bytes={}",
608 counter, output_hash[3], output_hash[2], output_hash[1], output_hash[0], status, processed
609 );
610
611 Ok(())
612}
613
614fn uuid_to_teec_uuid(uuid: &Uuid) -> Result<raw::TEEC_UUID> {
615 let (time_low, time_mid, time_hi_and_version, clock_seq_and_node) = uuid.as_fields();
616
617 Ok(raw::TEEC_UUID {
618 timeLow: time_low,
619 timeMid: time_mid,
620 timeHiAndVersion: time_hi_and_version,
621 clockSeqAndNode: *clock_seq_and_node,
622 })
623}