optee-utee/src/ta_session.rs (103 lines of code) (raw):
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use crate::{Error, Result, TeeParams, Uuid};
use optee_utee_sys as raw;
pub struct TaSessionBuilder<'a> {
target_uuid: Uuid,
timeout: u32,
params: Option<TeeParams<'a>>,
}
impl<'a> TaSessionBuilder<'a> {
/// Creates a new builder for the given TA UUID.
pub fn new(uuid: Uuid) -> Self {
Self {
target_uuid: uuid,
timeout: raw::TEE_TIMEOUT_INFINITE,
params: None,
}
}
/// Sets a custom timeout for the session opening.
pub fn with_timeout(mut self, timeout: u32) -> Self {
self.timeout = timeout;
self
}
/// Sets the parameters to be passed during session opening.
pub fn with_params(mut self, params: TeeParams<'a>) -> Self {
self.params = Some(params);
self
}
/// Builds and opens the `TaSession`. Returns an error if the session fails to open.
pub fn build(mut self) -> Result<TaSession> {
let mut err_origin: u32 = 0;
let mut raw_session: raw::TEE_TASessionHandle = core::ptr::null_mut();
// Check if the parameters are provided and prepare them for the C API call.
let (raw_param_types, raw_params_ptr, raw_params_opt) =
if let Some(params) = &mut self.params {
let mut raw_params = params.as_raw();
let raw_ptr = raw_params.as_mut_ptr();
(params.raw_param_types(), raw_ptr, Some(raw_params))
} else {
(0, core::ptr::null_mut(), None)
};
// SAFETY:
// self.target_uuid.as_raw_ptr() provides a valid pointer to the UUID.
// raw_params.as_mut_ptr() provides a valid pointer to the parameters.
// The remaining arguments are either valid values or null/mut pointers as expected by the C API.
// For parameters that are intended to be modified by the call, the buffer constraints are checked later in update_from_raw().
match unsafe {
raw::TEE_OpenTASession(
self.target_uuid.as_raw_ptr(),
self.timeout,
raw_param_types,
raw_params_ptr,
&mut raw_session,
&mut err_origin,
)
} {
raw::TEE_SUCCESS => {
if let (Some(params), Some(raw_params)) = (&mut self.params, raw_params_opt) {
params.update_from_raw(&raw_params)?;
}
Ok(TaSession { raw: raw_session })
}
code => Err(Error::from_raw_error(code).with_origin(err_origin.into())),
}
}
}
pub struct TaSession {
raw: raw::TEE_TASessionHandle,
}
impl TaSession {
/// Invokes a command with the provided parameters using the session's default timeout.
/// Returns the result directly without allowing further method chaining.
pub fn invoke_command(&mut self, command_id: u32, params: &mut TeeParams) -> Result<()> {
self.invoke_command_with_timeout(command_id, params, raw::TEE_TIMEOUT_INFINITE)
}
pub fn invoke_command_with_timeout(
&mut self,
command_id: u32,
params: &mut TeeParams,
timeout: u32,
) -> Result<()> {
let mut err_origin: u32 = 0;
let mut raw_params = params.as_raw();
let param_types = params.raw_param_types();
// SAFETY:
// self.raw is a valid pointer to an active session handle.
// raw_params.as_mut_ptr() yields a valid mutable pointer to the parameters array.
// The remaining arguments are either valid values or null/mutable pointers, as expected by the C API.
// For parameters that are intended to be modified by the call, the buffer constraints are checked later in update_from_raw().
match unsafe {
raw::TEE_InvokeTACommand(
self.raw,
timeout,
command_id,
param_types,
raw_params.as_mut_ptr(),
&mut err_origin,
)
} {
raw::TEE_SUCCESS => {
// Update the parameters with the results
params.update_from_raw(&raw_params)?;
Ok(())
}
code => Err(Error::from_raw_error(code).with_origin(err_origin.into())),
}
}
}
// Drop implementation to close the session
impl Drop for TaSession {
fn drop(&mut self) {
// SAFETY:
// self.raw is a valid pointer to an active session handle.
// The function call is expected to clean up the session resources.
unsafe {
raw::TEE_CloseTASession(self.raw);
}
}
}