optee_utee/parameter/mod.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! TEE parameter handling: conversion from raw OP-TEE parameter types into
19//! type-safe Rust wrappers.
20//!
21//! # Overview
22//!
23//! OP-TEE passes up to four parameters between the host (Normal World) and
24//! the TA (Trusted Application). Each parameter has an associated *type* tag
25//! (e.g. value, memref) and a raw `TEE_Param` union. This module provides:
26//!
27//! * **`FromRawParameter`** – single-parameter conversion from a raw
28//! `TEE_Param` into a typed Rust wrapper.
29//! * **`FromRawParameters`** – batch conversion of all four parameters at once
30//! (implemented for 4-tuples of `FromRawParameter` types).
31//! * **Typed wrappers** – `ParameterNone`, `ParameterValueInput`,
32//! `ParameterMemrefInput`, etc.
33//! * **Type-erased wrapper** – [`ParameterAny`] for scenarios where the
34//! developer cannot know the parameter type at compile time.
35//! * **Legacy compatibility** – [`deprecated`] provides the old unsafe
36//! pointer-based API; new code should use the typed wrappers instead.
37//!
38//! # Migration from the deprecated API
39//!
40//! If you currently use [`deprecated::Parameters`] and [`deprecated::Parameter`]:
41//!
42//! | Old pattern | New pattern |
43//! |---|---|
44//! | `params.0.as_value()?.a()` | `param.get_a()` via [`ParameterValueRead`](crate::ParameterValueRead] |
45//! | `params.0.as_memref()?.buffer()` | `param.read_to_vec()` / `param.read_at()` via [`crate::ParameterMemrefRead`], or `param.set_output()` / `param.write_at()` via [`crate::ParameterMemrefWrite`] |
46//! | `params.0.set_updated_size(n)` | `param.set_updated_size(n)` via [`crate::ParameterMemrefWrite`] |
47//!
48//! See the [`deprecated`] module for per-type migration notes.
49
50use crate::{ErrorKind, Result, raw};
51
52pub mod deprecated;
53pub mod memref;
54pub mod none;
55pub mod value;
56
57/// Raw parameter-type tag as passed by the TEE runtime.
58/// Each of the four slots carries a 4-bit type-identifier. Use
59/// `TEE_PARAM_TYPE_GET(raw_types, idx)` to extract one slot from
60/// the `RawParamTypes` bit-field.
61pub type RawParamType = u32;
62
63/// Together with a [`RawParams`] array this describes the name *and* content
64/// of all four TEE parameters.
65pub type RawParamTypes = u32;
66
67/// Array of four raw `TEE_Param` unions.
68///
69/// Corresponds to the four parameter slots passed to every TA entry-point.
70pub type RawParams = [raw::TEE_Param; raw::TEE_NUM_PARAMS as usize];
71
72/// Convert a single raw parameter into a type-safe Rust wrapper.
73///
74/// # Safety
75///
76/// Implementors must validate that `raw_type` matches the expected parameter
77/// type and that `raw_param` has been correctly initialized by the TEE
78/// runtime before reading any fields.
79pub trait FromRawParameter<'a>: Sized {
80 /// Construct `Self` from a raw parameter.
81 ///
82 /// # Safety
83 ///
84 /// Caller must ensure `raw_type` and `raw_param` are a consistent pair
85 /// delivered by a TEE entry-point invocation (e.g. `TA_InvokeCommandEntryPoint`).
86 #[allow(clippy::missing_safety_doc)]
87 unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut raw::TEE_Param) -> Result<Self>;
88}
89
90/// Convert all four raw parameters at once into a typed tuple.
91///
92/// # Safety
93///
94/// The same safety constraints as [`FromRawParameter`] apply to each slot.
95pub trait FromRawParameters<'a>: Sized {
96 /// Construct `Self` from the full parameter array.
97 ///
98 /// # Safety
99 ///
100 /// Caller must ensure `raw_types` and `raw_param` come from the same
101 /// TEE entry-point invocation.
102 #[allow(clippy::missing_safety_doc)]
103 unsafe fn from_raw(raw_types: RawParamTypes, raw_params: &'a mut RawParams) -> Result<Self>;
104}
105
106impl<
107 'a,
108 A: FromRawParameter<'a>,
109 B: FromRawParameter<'a>,
110 C: FromRawParameter<'a>,
111 D: FromRawParameter<'a>,
112> FromRawParameters<'a> for (A, B, C, D)
113{
114 unsafe fn from_raw(raw_types: RawParamTypes, raw_params: &'a mut RawParams) -> Result<Self> {
115 Ok(unsafe {
116 let [p0, p1, p2, p3] = raw_params;
117 (
118 A::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 0), p0)?,
119 B::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 1), p1)?,
120 C::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 2), p2)?,
121 D::from_raw(raw::TEE_PARAM_TYPE_GET(raw_types, 3), p3)?,
122 )
123 })
124 }
125}
126
127/// Enumerates the seven standard TEE parameter types.
128///
129/// This is the Rust-side mirror of the `TEE_PARAM_TYPE_*` constants defined
130/// in the C header. The `Unknown(u32)` variant catches any
131/// implementation-defined or invalid type tags.
132#[derive(Copy, Clone, num_enum::FromPrimitive, num_enum::IntoPrimitive)]
133#[repr(u32)]
134pub enum ParamType {
135 None = raw::TEE_PARAM_TYPE_NONE,
136 ValueInput = raw::TEE_PARAM_TYPE_VALUE_INPUT,
137 ValueOutput = raw::TEE_PARAM_TYPE_VALUE_OUTPUT,
138 ValueInout = raw::TEE_PARAM_TYPE_VALUE_INOUT,
139 MemrefInput = raw::TEE_PARAM_TYPE_MEMREF_INPUT,
140 MemrefOutput = raw::TEE_PARAM_TYPE_MEMREF_OUTPUT,
141 MemrefInout = raw::TEE_PARAM_TYPE_MEMREF_INOUT,
142 #[num_enum(catch_all)]
143 Unknown(u32),
144}
145
146fn check_type_is(raw_type: RawParamType, exp_type: ParamType) -> Result<()> {
147 let exp_type: u32 = exp_type.into();
148 if raw_type != exp_type {
149 return Err(ErrorKind::BadParameters.into());
150 }
151 Ok(())
152}
153
154/// A type-erased parameter that dispatches to the correct concrete wrapper
155/// based on the runtime type tag.
156///
157/// # When to use
158///
159/// Use `ParameterAny` when the parameter type is **not known at compile time**
160/// and must be determined at runtime. Typical scenarios:
161///
162/// * The command semantics allow multiple parameter types for the same slot
163/// (e.g. "slot 0 may be `None` or `MemrefInput` depending on the command").
164/// * A library helper is designed to inspect parameters generically without
165/// fixing the types in its signature.
166///
167/// If you already know the expected type for a slot, prefer the concrete
168/// wrappers from [`value`] and [`memref`] instead—they provide methods
169/// specific to that type and avoid the match ceremony.
170///
171/// # Example
172///
173/// ```rust,ignore
174/// use optee_utee::parameter::{ParameterAny, FromRawParameter};
175///
176/// match param {
177/// ParameterAny::None => { /* no parameter */ }
178/// ParameterAny::MemrefInput(p) => {
179/// let data: alloc::vec::Vec<u8> = p.read_to_vec();
180/// // validate and use the TA-owned `data` ...
181/// }
182/// ParameterAny::ValueInput(p) => {
183/// let a = p.get_a();
184/// let b = p.get_b();
185/// // use a, b ...
186/// }
187/// _ => return Err(ErrorKind::BadParameters.into()),
188/// }
189/// ```
190pub enum ParameterAny<'a> {
191 None,
192 ValueInput(value::ParameterValueInput),
193 ValueInout(value::ParameterValueInout<'a>),
194 ValueOutput(value::ParameterValueOutput<'a>),
195 MemrefInput(memref::ParameterMemrefInput<'a>),
196 MemrefInout(memref::ParameterMemrefInout<'a>),
197 MemrefOutput(memref::ParameterMemrefOutput<'a>),
198 /// Unrecognized or implementation-defined type tag.
199 ///
200 /// Carries the raw `RawParamType` and a mutable reference to the
201 /// underlying `TEE_Param` so that the caller can handle it manually.
202 Unknown(RawParamType, &'a mut raw::TEE_Param),
203}
204
205impl<'a> ParameterAny<'a> {
206 pub fn as_value_input(&self) -> Result<&value::ParameterValueInput> {
207 match &self {
208 Self::ValueInput(p) => Ok(p),
209 _ => Err(ErrorKind::BadParameters.into()),
210 }
211 }
212 pub fn as_value_output(&mut self) -> Result<&mut value::ParameterValueOutput<'a>> {
213 match self {
214 Self::ValueOutput(p) => Ok(p),
215 _ => Err(ErrorKind::BadParameters.into()),
216 }
217 }
218 pub fn as_value_inout(&mut self) -> Result<&mut value::ParameterValueInout<'a>> {
219 match self {
220 Self::ValueInout(p) => Ok(p),
221 _ => Err(ErrorKind::BadParameters.into()),
222 }
223 }
224 pub fn as_memref_input(&self) -> Result<&memref::ParameterMemrefInput<'a>> {
225 match self {
226 Self::MemrefInput(p) => Ok(p),
227 _ => Err(ErrorKind::BadParameters.into()),
228 }
229 }
230 pub fn as_memref_inout(&mut self) -> Result<&mut memref::ParameterMemrefInout<'a>> {
231 match self {
232 Self::MemrefInout(p) => Ok(p),
233 _ => Err(ErrorKind::BadParameters.into()),
234 }
235 }
236 pub fn as_memref_output(&mut self) -> Result<&mut memref::ParameterMemrefOutput<'a>> {
237 match self {
238 Self::MemrefOutput(p) => Ok(p),
239 _ => Err(ErrorKind::BadParameters.into()),
240 }
241 }
242 pub fn as_none(&self) -> Result<()> {
243 match self {
244 Self::None => Ok(()),
245 _ => Err(ErrorKind::BadParameters.into()),
246 }
247 }
248}
249
250impl<'a> FromRawParameter<'a> for ParameterAny<'a> {
251 unsafe fn from_raw(raw_type: RawParamType, raw_param: &'a mut raw::TEE_Param) -> Result<Self> {
252 unsafe {
253 match raw_type {
254 raw::TEE_PARAM_TYPE_NONE => Ok(Self::None),
255 raw::TEE_PARAM_TYPE_VALUE_INPUT => Ok(Self::ValueInput(
256 value::ParameterValueInput::from_raw(raw_type, raw_param)?,
257 )),
258 raw::TEE_PARAM_TYPE_VALUE_INOUT => Ok(Self::ValueInout(
259 value::ParameterValueInout::from_raw(raw_type, raw_param)?,
260 )),
261 raw::TEE_PARAM_TYPE_VALUE_OUTPUT => Ok(Self::ValueOutput(
262 value::ParameterValueOutput::from_raw(raw_type, raw_param)?,
263 )),
264 raw::TEE_PARAM_TYPE_MEMREF_INPUT => Ok(Self::MemrefInput(
265 memref::ParameterMemrefInput::from_raw(raw_type, raw_param)?,
266 )),
267 raw::TEE_PARAM_TYPE_MEMREF_INOUT => Ok(Self::MemrefInout(
268 memref::ParameterMemrefInout::from_raw(raw_type, raw_param)?,
269 )),
270 raw::TEE_PARAM_TYPE_MEMREF_OUTPUT => Ok(Self::MemrefOutput(
271 memref::ParameterMemrefOutput::from_raw(raw_type, raw_param)?,
272 )),
273 _ => Ok(Self::Unknown(raw_type, raw_param)),
274 }
275 }
276 }
277}
278
279pub type ParametersAny<'a> = (
280 ParameterAny<'a>,
281 ParameterAny<'a>,
282 ParameterAny<'a>,
283 ParameterAny<'a>,
284);
285pub type ParametersNone = (
286 none::ParameterNone,
287 none::ParameterNone,
288 none::ParameterNone,
289 none::ParameterNone,
290);