optee_utee/object/transient_object.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
18use alloc::vec::Vec;
19
20use optee_utee_sys as raw;
21
22use super::{Attribute, GenericObject, ObjectHandle};
23use crate::{Error, Result};
24
25/// Define types of [TransientObject](crate::TransientObject) with
26/// predefined maximum sizes.
27#[repr(u32)]
28pub enum TransientObjectType {
29 /// 128, 192, or 256 bits
30 Aes = 0xA0000010,
31 /// Always 64 bits including the parity bits. This gives an effective key
32 /// size of 56 bits
33 Des = 0xA0000011,
34 /// 128 or 192 bits including the parity bits. This gives effective key
35 /// sizes of 112 or 168 bits
36 Des3 = 0xA0000013,
37 /// Between 64 and 512 bits, multiple of 8 bits
38 HmacMd5 = 0xA0000001,
39 /// Between 80 and 512 bits, multiple of 8 bits
40 HmacSha1 = 0xA0000002,
41 /// Between 112 and 512 bits, multiple of 8 bits
42 HmacSha224 = 0xA0000003,
43 /// Between 192 and 1024 bits, multiple of 8 bits
44 HmacSha256 = 0xA0000004,
45 /// Between 256 and 1024 bits, multiple of 8 bits
46 HmacSha384 = 0xA0000005,
47 /// Between 256 and 1024 bits, multiple of 8 bits
48 HmacSha512 = 0xA0000006,
49 /// The number of bits in the modulus. 256, 512, 768, 1024, 1536 and
50 /// 2048-bit keys SHALL be supported.
51 /// Support for other key sizes including bigger key sizes is
52 /// implementation-dependent. Minimum key size is 256 bits
53 RsaPublicKey = 0xA0000030,
54 /// Same as [RsaPublicKey](crate::TransientObjectType::RsaPublicKey) key
55 /// size.
56 RsaKeypair = 0xA1000030,
57 /// Depends on Algorithm:
58 /// 1) [DsaSha1](crate::AlgorithmId::DsaSha1):
59 /// Between 512 and 1024 bits, multiple of 64 bits
60 /// 2) [DsaSha224](crate::AlgorithmId::DsaSha224): 2048 bits
61 /// 3) [DsaSha256](crate::AlgorithmId::DsaSha256): 2048 or 3072 bits
62 DsaPublicKey = 0xA0000031,
63 /// Same as [DsaPublicKey](crate::TransientObjectType::DsaPublicKey) key
64 /// size.
65 DsaKeypair = 0xA1000031,
66 /// From 256 to 2048 bits, multiple of 8 bits.
67 DhKeypair = 0xA1000032,
68 /// Between 160 and 521 bits. Conditional: Available only if at least
69 /// one of the ECC the curves defined in Table 6-14 with "generic"
70 /// equal to "Y" is supported.
71 EcdsaPublicKey = 0xA0000041,
72 /// Between 160 and 521 bits. Conditional: Available only if at least
73 /// one of the ECC curves defined in Table 6-14 with "generic" equal to
74 /// "Y" is supported. SHALL be same value as for ECDSA public key size.
75 EcdsaKeypair = 0xA1000041,
76 /// Between 160 and 521 bits. Conditional: Available only if at least
77 /// one of the ECC curves defined in Table 6-14 with "generic" equal to
78 /// "Y" is supported.
79 EcdhPublicKey = 0xA0000042,
80 /// Between 160 and 521 bits. Conditional: Available only if at least
81 /// one of the ECC curves defined in Table 6-14 with "generic" equal to
82 /// "Y" is supported. SHALL be same value as for ECDH public key size
83 EcdhKeypair = 0xA1000042,
84 /// 256 bits. Conditional: Available only if TEE_ECC_CURVE_25519
85 /// defined in Table 6-14 is supported.
86 Ed25519PublicKey = 0xA0000043,
87 /// 256 bits. Conditional: Available only if TEE_ECC_CURVE_25519
88 /// defined in Table 6-14 is supported.
89 Ed25519Keypair = 0xA1000043,
90 /// 256 bits. Conditional: Available only if TEE_ECC_CURVE_25519
91 /// defined in Table 6-14 is supported.
92 X25519PublicKey = 0xA0000044,
93 /// 256 bits. Conditional: Available only if TEE_ECC_CURVE_25519
94 /// defined in Table 6-14 is supported.
95 X25519Keypair = 0xA1000044,
96 /// Multiple of 8 bits, up to 4096 bits. This type is intended for secret
97 /// data that has been derived from a key derivation scheme.
98 GenericSecret = 0xA0000000,
99 /// Object is corrupted.
100 CorruptedObject = 0xA00000BE,
101 /// 0 – All data is in the associated data stream.
102 Data = 0xA00000BF,
103}
104
105/// An object containing attributes but no data stream, which is reclaimed
106/// when closed or when the TA instance is destroyed.
107/// Transient objects are used to hold a cryptographic object (key or key-pair).
108///
109/// Contrast [PersistentObject](crate::PersistentObject).
110#[derive(Debug)]
111pub struct TransientObject(ObjectHandle);
112
113impl TransientObject {
114 /// Create an object with a null handle which points to nothing.
115 //
116 // TODO: This function is only used in examples and should be removed when
117 // TransientObject is fully refactored in the future. Keep it for now and
118 // leave it for future PR.
119 pub fn null_object() -> Self {
120 Self(ObjectHandle::new_null())
121 }
122
123 /// Check if current object is created with null handle.
124 ///
125 /// # See Also
126 ///
127 /// - [Self::null_object](Self::null_object).
128 pub fn is_null_object(&self) -> bool {
129 self.0.is_null()
130 }
131
132 /// Allocate an uninitialized object, i.e. a container for attributes.
133 ///
134 /// As allocated, the object is uninitialized.
135 /// It can be initialized by subsequently importing the object material,
136 /// generating an object, deriving an object, or loading an object from the
137 /// Trusted Storage.
138 ///
139 /// # Parameters
140 ///
141 /// 1) `object_type`: Type of uninitialized object container to be created
142 /// as defined in [TransientObjectType](crate::TransientObjectType).
143 /// 2) `max_object_size`: Key Size of the object. Valid values depend on the
144 /// object type and are defined in
145 /// [TransientObjectType](crate::TransientObjectType).
146 ///
147 /// # Example
148 ///
149 /// ``` rust,no_run
150 /// # use optee_utee::{TransientObject, TransientObjectType};
151 /// # fn main() -> optee_utee::Result<()> {
152 /// match TransientObject::allocate(TransientObjectType::Aes, 128) {
153 /// Ok(object) =>
154 /// {
155 /// // ...
156 /// Ok(())
157 /// }
158 /// Err(e) => Err(e),
159 /// }
160 /// # }
161 /// ```
162 ///
163 /// # Errors
164 ///
165 /// 1) `OutOfMemory`: If not enough resources are available to allocate the
166 /// object handle.
167 /// 2) `NotSupported`: If the key size is not supported or the object type
168 /// is not supported.
169 ///
170 /// # Panics
171 ///
172 /// 1) If the Implementation detects any error associated with this function
173 /// which is not explicitly associated with a defined return code for
174 /// this function.
175 pub fn allocate(object_type: TransientObjectType, max_object_size: usize) -> Result<Self> {
176 let mut handle: raw::TEE_ObjectHandle = core::ptr::null_mut();
177 // Move as much code as possible out of unsafe blocks to maximize Rust’s
178 // safety checks.
179 let handle_mut = &mut handle;
180 match unsafe {
181 raw::TEE_AllocateTransientObject(object_type as u32, max_object_size as u32, handle_mut)
182 } {
183 raw::TEE_SUCCESS => Ok(Self(ObjectHandle::from_raw(handle)?)),
184 code => Err(Error::from_raw_error(code)),
185 }
186 }
187
188 /// Reset the object to its initial state after allocation.
189 /// If the object is currently initialized, the function clears the object
190 /// of all its material.
191 /// The object is then uninitialized again.
192 pub fn reset(&mut self) {
193 unsafe {
194 raw::TEE_ResetTransientObject(*self.as_raw_ref());
195 }
196 }
197
198 /// Populate an uninitialized object container with object attributes passed
199 /// by the TA in the `attrs` parameter.
200 /// When this function is called, the object SHALL be uninitialized.
201 /// If the object is initialized, the caller SHALL first clear it using the
202 /// function reset.
203 /// Note that if the object type is a key-pair, then this function sets both
204 /// the private and public attributes of the keypair.
205 ///
206 /// # Parameters
207 ///
208 /// 1) `attrs`: Array of object attributes.
209 ///
210 /// # Example
211 ///
212 /// ``` rust,no_run
213 /// # use optee_utee::{
214 /// # TransientObject,
215 /// # TransientObjectType,
216 /// # AttributeMemref,
217 /// # AttributeId,
218 /// # };
219 /// # fn main() -> optee_utee::Result<()> {
220 /// match TransientObject::allocate(TransientObjectType::Aes, 128) {
221 /// Ok(mut object) =>
222 /// {
223 /// let attrs = [AttributeMemref::from_ref(AttributeId::SecretValue, &[0u8;1]).into()];
224 /// object.populate(&attrs);
225 /// Ok(())
226 /// }
227 /// Err(e) => Err(e),
228 /// }
229 /// # }
230 /// ```
231 ///
232 /// # Errors
233 ///
234 /// 1) `BadParameters`: If an incorrect or inconsistent attribute value is
235 /// detected. In this case, the content of the object SHALL remain
236 /// uninitialized.
237 ///
238 /// # Panics
239 ///
240 /// 1) If object is not a valid opened object that is transient and
241 /// uninitialized.
242 /// 2) If some mandatory attribute is missing.
243 /// 3) If an attribute which is not defined for the object’s type is
244 /// present in attrs.
245 /// 4) If an attribute value is too big to fit within the maximum object
246 /// size specified when the object was created.
247 /// 5) If the Implementation detects any other error associated with this
248 /// function which is not explicitly associated with a defined return
249 /// code for this function.
250 pub fn populate(&mut self, attrs: &[Attribute]) -> Result<()> {
251 let p: Vec<raw::TEE_Attribute> = attrs.iter().map(|p| p.raw()).collect();
252 match unsafe {
253 raw::TEE_PopulateTransientObject(
254 *self.0.as_raw_ref(),
255 p.as_ptr() as _,
256 attrs.len() as u32,
257 )
258 } {
259 raw::TEE_SUCCESS => Ok(()),
260 code => Err(Error::from_raw_error(code)),
261 }
262 }
263
264 /// Populates an uninitialized object handle with the attributes of another
265 /// object handle;
266 /// that is, it populates the attributes of this handle with the attributes
267 /// of src_handle.
268 /// It is most useful in the following situations:
269 /// 1) To extract the public key attributes from a key-pair object.
270 /// 2) To copy the attributes from a
271 /// [PersistentObject](crate::PersistentObject) into a
272 /// [TransientObject](crate::TransientObject).
273 ///
274 /// # Parameters
275 ///
276 /// 1) `src_object`: Can be either a
277 /// [TransientObject](crate::TransientObject) or
278 /// [PersistentObject](crate::PersistentObject).
279 ///
280 /// # Example
281 ///
282 /// ``` rust,no_run
283 /// # use optee_utee::{TransientObject, TransientObjectType};
284 /// # fn main() -> optee_utee::Result<()> {
285 /// match TransientObject::allocate(TransientObjectType::Aes, 128) {
286 /// Ok(mut object1) =>
287 /// {
288 /// match TransientObject::allocate(TransientObjectType::Aes, 256) {
289 /// Ok(object2) => {
290 /// object1.copy_attribute_from(&object2);
291 /// Ok(())
292 /// }
293 /// Err(e) => Err(e),
294 /// }
295 /// }
296 /// Err(e) => Err(e),
297 /// }
298 /// # }
299 /// ```
300 ///
301 /// # Errors
302 ///
303 /// 1) `CorruptObject`: If the persistent object is corrupt. The object
304 /// handle SHALL behave based on the
305 /// `gpd.ta.doesNotCloseHandleOnCorruptObject` property.
306 /// 2) `StorageNotAvailable`: If the persistent object is stored in a
307 /// storage area which is currently inaccessible.
308 ///
309 /// # Panics
310 ///
311 /// 1) If src_object is not initialized.
312 /// 2) If self is initialized.
313 /// 3) If the type and size of src_object and self are not compatible.
314 /// 4) If the Implementation detects any other error associated with this
315 /// function which is not explicitly associated with a defined return
316 /// code for this function.
317 pub fn copy_attribute_from<T: GenericObject>(&mut self, src_object: &T) -> Result<()> {
318 match unsafe {
319 raw::TEE_CopyObjectAttributes1(*self.as_raw_ref(), *src_object.as_raw_ref())
320 } {
321 raw::TEE_SUCCESS => Ok(()),
322 code => Err(Error::from_raw_error(code)),
323 }
324 }
325
326 /// Generates a random key or a key-pair and populates a transient key
327 /// object with the generated key material.
328 ///
329 /// # Parameters
330 ///
331 /// 1) `key_size`: the size of the desired key. It SHALL be less than or
332 /// equal to the maximum key size specified when the transient object
333 /// was created.
334 ///
335 /// # Example
336 ///
337 /// ``` rust,no_run
338 /// # use optee_utee::{TransientObject, TransientObjectType};
339 /// # fn main() -> optee_utee::Result<()> {
340 /// match TransientObject::allocate(TransientObjectType::Aes, 128) {
341 /// Ok(object) =>
342 /// {
343 /// object.generate_key(128, &[])?;
344 /// Ok(())
345 /// }
346 /// Err(e) => Err(e),
347 /// }
348 /// # }
349 /// ```
350 ///
351 /// # Errors
352 ///
353 /// 1) `BadParameters`: If an incorrect or inconsistent attribute value is detected. In this
354 /// case, the content of the object SHALL remain uninitialized.
355 ///
356 /// # Panics
357 ///
358 /// 1) If object is not a valid opened object.
359 /// 2) If some mandatory attribute is missing.
360 /// 3) If an attribute which is not defined for the object’s type is present
361 /// in attrs.
362 /// 4) If an attribute value is too big to fit within the maximum object
363 /// size specified when the object was created.
364 /// 5) If the Implementation detects any other error associated with this
365 /// function which is not explicitly associated with a defined return
366 /// code for this function.
367 pub fn generate_key(&self, key_size: usize, params: &[Attribute]) -> Result<()> {
368 let p: Vec<raw::TEE_Attribute> = params.iter().map(|p| p.raw()).collect();
369 unsafe {
370 match raw::TEE_GenerateKey(
371 *self.as_raw_ref(),
372 key_size as u32,
373 p.as_slice().as_ptr() as _,
374 p.len() as u32,
375 ) {
376 raw::TEE_SUCCESS => Ok(()),
377 code => Err(Error::from_raw_error(code)),
378 }
379 }
380 }
381}
382
383impl GenericObject for TransientObject {
384 unsafe fn as_raw_ref(&self) -> &optee_utee_sys::TEE_ObjectHandle {
385 unsafe { self.0.as_raw_ref() }
386 }
387}
388
389#[cfg(test)]
390mod tests {
391 use optee_utee_sys::{
392 mock_api,
393 mock_utils::{SERIAL_TEST_LOCK, object::MockHandle},
394 };
395
396 use super::*;
397
398 #[test]
399 // If a transient object is successfully allocated, TEE_CloseObject will be
400 // called when it is dropped.
401 //
402 // According to `GPD_TEE_Internal_Core_API_Specification_v1.3.1`:
403 // At 5.5.5 TEE_CloseObject:
404 // The `TEE_CloseObject` function closes an opened object handle. The object
405 // can be persistent or transient.
406 // For transient objects, `TEE_CloseObject` is equivalent to
407 // `TEE_FreeTransientObject`.
408 fn test_allocate_and_drop() {
409 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
410
411 let mut raw_handle = MockHandle::new();
412 let handle = raw_handle.as_handle();
413 let fn1 = mock_api::TEE_AllocateTransientObject_context();
414 let fn2 = mock_api::TEE_CloseObject_context();
415
416 fn1.expect().return_once_st(move |_, _, obj| {
417 unsafe { *obj = handle.clone() };
418 raw::TEE_SUCCESS
419 });
420 fn2.expect().return_once_st(move |obj| {
421 debug_assert_eq!(obj, handle.clone());
422 });
423
424 let _obj =
425 TransientObject::allocate(TransientObjectType::Aes, 128).expect("it should be ok");
426 }
427
428 #[test]
429 fn test_allocate_fail() {
430 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
431
432 static RETURN_CODE: raw::TEE_Result = raw::TEE_ERROR_BAD_STATE;
433 let fn1 = mock_api::TEE_AllocateTransientObject_context();
434
435 fn1.expect().return_const(RETURN_CODE);
436
437 let err =
438 TransientObject::allocate(TransientObjectType::Aes, 128).expect_err("it should be err");
439
440 assert_eq!(err.raw_code(), RETURN_CODE);
441 }
442}