| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| mod tee_client_api; |
| |
| use self::tee_client_api::*; |
| use log::error; |
| use std::mem; |
| use std::ptr; |
| |
| use self::tee_client_api::{ |
| teec_operation_impl, TEEC_Operation as TeecOperation, |
| TEEC_TempMemoryReference as TeecTempMemoryReference, TEEC_Value as TeecValue, |
| }; |
| |
| pub use self::tee_client_api::{ |
| TEEC_Parameter as TeecParameter, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_OUTPUT, TEEC_NONE, |
| TEEC_VALUE_INPUT, |
| }; |
| |
| /// The TA UUID for keysafe: the trust side app for KMS. |
| pub static KEYSAFE_TA_UUID: TEEC_UUID = TEEC_UUID { |
| timeLow: 0x808032e0, |
| timeMid: 0xfd9e, |
| timeHiAndVersion: 0x4e6f, |
| clockSeqAndNode: [0x88, 0x96, 0x54, 0x47, 0x35, 0xc9, 0x84, 0x80], |
| }; |
| |
| /// Gets a None parameter. |
| pub fn get_zero_parameter() -> TeecParameter { |
| let zero_parameter: TeecParameter = unsafe { mem::zeroed() }; |
| zero_parameter |
| } |
| |
| /// Gets a value parameter. |
| pub fn get_value_parameter(a: u32, b: u32) -> TeecParameter { |
| TeecParameter { value: TeecValue { a, b } } |
| } |
| |
| /// Gets a temp memory reference parameter as output. |
| pub fn get_memref_output_parameter(data: &mut [u8]) -> TeecParameter { |
| TeecParameter { |
| tmpref: TeecTempMemoryReference { |
| buffer: data.as_mut_ptr() as *mut std::ffi::c_void, |
| size: data.len(), |
| }, |
| } |
| } |
| |
| /// Gets a temp memory reference parameter as input. |
| pub fn get_memref_input_parameter(data: &[u8]) -> TeecParameter { |
| TeecParameter { |
| tmpref: TeecTempMemoryReference { |
| buffer: data.as_ptr() as *mut std::ffi::c_void, |
| size: data.len(), |
| }, |
| } |
| } |
| |
| /// Creates an operation object that would be used in call_command. |
| pub fn create_operation(param_type: u32, params: [TeecParameter; 4]) -> TeecOperation { |
| TeecOperation { |
| started: 0, |
| paramTypes: param_type, |
| params, |
| imp: teec_operation_impl { reserved: 0 as ::std::os::raw::c_char }, |
| } |
| } |
| |
| /// Creates a temporary session and call a command. |
| /// |
| /// Returns error code on failure. |
| pub fn call_command(op: &mut TeecOperation, command_id: u32) -> Result<(), u32> { |
| let mut tee_context = TeeContext::new()?; |
| let mut tee_session = tee_context.new_session()?; |
| let mut return_origin: u32 = 0; |
| tee_session.invoke_command(command_id, op, &mut return_origin) |
| } |
| |
| struct TeeContext { |
| context: TEEC_Context, |
| } |
| |
| impl TeeContext { |
| pub fn new() -> Result<Self, u32> { |
| let mut context: TEEC_Context = unsafe { mem::zeroed() }; |
| let result = unsafe { TEEC_InitializeContext(ptr::null(), &mut context) }; |
| if result != TEEC_SUCCESS { |
| error!("Failed to initialize context: {:?}", result); |
| return Err(result); |
| } |
| Ok(TeeContext { context }) |
| } |
| |
| pub fn new_session(&mut self) -> Result<TeeSession, u32> { |
| let mut session: TEEC_Session = unsafe { mem::zeroed() }; |
| |
| let mut return_origin: u32 = 0; |
| let result = unsafe { |
| TEEC_OpenSession( |
| &mut self.context, |
| &mut session, |
| &KEYSAFE_TA_UUID, |
| TEEC_LOGIN_PUBLIC, |
| ptr::null_mut(), |
| ptr::null_mut(), |
| &mut return_origin, |
| ) |
| }; |
| if result != TEEC_SUCCESS { |
| error!("Failed to open session ({:?} {:?})\n", result, return_origin); |
| return Err(result); |
| } |
| Ok(TeeSession { session }) |
| } |
| } |
| |
| impl Drop for TeeContext { |
| fn drop(&mut self) { |
| unsafe { TEEC_FinalizeContext(&mut self.context) }; |
| } |
| } |
| |
| struct TeeSession { |
| session: TEEC_Session, |
| } |
| |
| impl TeeSession { |
| pub fn invoke_command( |
| &mut self, |
| command_id: u32, |
| operation: *mut TEEC_Operation, |
| return_origin: *mut u32, |
| ) -> Result<(), u32> { |
| let result = |
| unsafe { TEEC_InvokeCommand(&mut self.session, command_id, operation, return_origin) }; |
| if result != TEEC_SUCCESS { |
| error!("TEEC_InvokeCommand failed with code {:?} origin {:?}", result, return_origin); |
| return Err(result); |
| } |
| Ok(()) |
| } |
| } |
| |
| impl Drop for TeeSession { |
| fn drop(&mut self) { |
| unsafe { TEEC_CloseSession(&mut self.session) }; |
| } |
| } |