1mod tee_client_api;
6
7use self::tee_client_api::*;
8use log::error;
9use std::{mem, ptr};
10
11use self::tee_client_api::{
12 TEEC_TempMemoryReference as TeecTempMemoryReference, TEEC_Value as TeecValue,
13};
14
15pub use self::tee_client_api::{
16 TEEC_Operation as TeecOperation, TEEC_Parameter as TeecParameter, TEEC_ERROR_NOT_SUPPORTED,
17 TEEC_ERROR_SHORT_BUFFER, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE,
18 TEEC_SUCCESS, TEEC_VALUE_INPUT,
19};
20
21pub static KEYSAFE_TA_UUID: TEEC_UUID = TEEC_UUID {
23 timeLow: 0x808032e0,
24 timeMid: 0xfd9e,
25 timeHiAndVersion: 0x4e6f,
26 clockSeqAndNode: [0x88, 0x96, 0x54, 0x47, 0x35, 0xc9, 0x84, 0x80],
27};
28
29pub fn teec_param_types(
31 param0_type: u32,
32 param1_type: u32,
33 param2_type: u32,
34 param3_type: u32,
35) -> u32 {
36 ((param0_type & 0xF) << 0)
37 | ((param1_type & 0xF) << 4)
38 | ((param2_type & 0xF) << 8)
39 | ((param3_type & 0xF) << 12)
40}
41
42pub fn get_zero_parameter() -> TeecParameter {
44 let zero_parameter: TeecParameter = unsafe { mem::zeroed() };
45 zero_parameter
46}
47
48pub fn get_value_parameter(a: u32, b: u32) -> TeecParameter {
50 TeecParameter { value: TeecValue { a, b } }
51}
52
53pub fn get_memref_output_parameter(data: &mut [u8]) -> TeecParameter {
55 TeecParameter {
56 tmpref: TeecTempMemoryReference {
57 buffer: data.as_mut_ptr() as *mut std::ffi::c_void,
58 size: data.len() as u64,
59 },
60 }
61}
62
63pub fn get_memref_input_parameter(data: &[u8]) -> TeecParameter {
65 TeecParameter {
66 tmpref: TeecTempMemoryReference {
67 buffer: data.as_ptr() as *mut std::ffi::c_void,
68 size: data.len() as u64,
69 },
70 }
71}
72
73pub fn create_operation(param_type: u32, params: [TeecParameter; 4]) -> TeecOperation {
75 TeecOperation {
76 started: 0,
77 paramTypes: param_type,
78 params,
79 imp: teec_operation_impl { reserved: 0 as ::std::os::raw::c_char },
80 }
81}
82
83pub fn call_command(op: &mut TeecOperation, command_id: u32) -> Result<(), u32> {
87 let mut tee_context = TeeContext::new()?;
88 let mut tee_session = tee_context.new_session()?;
89 let mut return_origin: u32 = 0;
90 tee_session.invoke_command(command_id, op, &mut return_origin)
91}
92
93pub fn call_command_on_device(
97 dev: &std::ffi::CStr,
98 op: &mut TeecOperation,
99 command_id: u32,
100) -> Result<(), u32> {
101 let mut tee_context = TeeContext::new_with_device(dev)?;
102 let mut tee_session = tee_context.new_session()?;
103 let mut return_origin: u32 = 0;
104 tee_session.invoke_command(command_id, op, &mut return_origin)
105}
106
107struct TeeContext {
108 context: TEEC_Context,
109}
110
111impl TeeContext {
112 pub fn new() -> Result<Self, u32> {
113 Self::new_with_ptr(ptr::null())
114 }
115
116 pub fn new_with_device(dev: &std::ffi::CStr) -> Result<Self, u32> {
117 Self::new_with_ptr(dev.as_ptr())
118 }
119
120 fn new_with_ptr(dev: *const std::os::raw::c_char) -> Result<Self, u32> {
121 let mut context: TEEC_Context = unsafe { mem::zeroed() };
122 let result = unsafe { TEEC_InitializeContext(dev, &mut context) };
123 if result != TEEC_SUCCESS {
124 error!("Failed to initialize context: {:?}", result);
125 return Err(result);
126 }
127 Ok(TeeContext { context })
128 }
129
130 pub fn new_session(&mut self) -> Result<TeeSession, u32> {
131 let mut session: TEEC_Session = unsafe { mem::zeroed() };
132
133 let mut return_origin: u32 = 0;
134 let result = unsafe {
135 TEEC_OpenSession(
136 &mut self.context,
137 &mut session,
138 &KEYSAFE_TA_UUID,
139 TEEC_LOGIN_PUBLIC,
140 ptr::null_mut(),
141 ptr::null_mut(),
142 &mut return_origin,
143 )
144 };
145 if result != TEEC_SUCCESS {
146 error!("Failed to open session ({:?} {:?})\n", result, return_origin);
147 return Err(result);
148 }
149 Ok(TeeSession { session })
150 }
151}
152
153impl Drop for TeeContext {
154 fn drop(&mut self) {
155 unsafe { TEEC_FinalizeContext(&mut self.context) };
156 }
157}
158
159struct TeeSession {
160 session: TEEC_Session,
161}
162
163impl TeeSession {
164 pub fn invoke_command(
165 &mut self,
166 command_id: u32,
167 operation: *mut TEEC_Operation,
168 return_origin: *mut u32,
169 ) -> Result<(), u32> {
170 let result =
171 unsafe { TEEC_InvokeCommand(&mut self.session, command_id, operation, return_origin) };
172 if result != TEEC_SUCCESS {
173 error!("TEEC_InvokeCommand failed with code {:?} origin {:?}", result, return_origin);
174 return Err(result);
175 }
176 Ok(())
177 }
178}
179
180impl Drop for TeeSession {
181 fn drop(&mut self) {
182 unsafe { TEEC_CloseSession(&mut self.session) };
183 }
184}