optee_utee/object/persistent_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 optee_utee_sys as raw;
19
20use super::{DataFlag, GenericObject, ObjectHandle, ObjectStorageConstants, Whence};
21use crate::{Error, Result};
22
23/// An object identified by an Object Identifier and including a Data Stream.
24///
25/// Contrast [TransientObject](crate::TransientObject).
26#[derive(Debug)]
27pub struct PersistentObject(ObjectHandle);
28
29impl PersistentObject {
30 /// Open an existing persistent object.
31 ///
32 /// # Parameters
33 ///
34 /// 1) `storage_id`: The storage to use which is defined in
35 /// [ObjectStorageConstants](crate::ObjectStorageConstants).
36 /// 2) `object_id`: The object identifier. Note that this buffer cannot
37 /// reside in shared memory.
38 /// 3) `flags`: The [DataFlag](crate::DataFlag) which determine the settings
39 /// under which the object is opened.
40 ///
41 /// # Example
42 ///
43 /// ``` rust,no_run
44 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
45 /// # fn main() -> optee_utee::Result<()> {
46 /// let obj_id = [1u8;1];
47 /// match PersistentObject::open(
48 /// ObjectStorageConstants::Private,
49 /// &obj_id,
50 /// DataFlag::ACCESS_READ) {
51 /// Ok(object) =>
52 /// {
53 /// // ...
54 /// Ok(())
55 /// }
56 /// Err(e) => Err(e),
57 /// }
58 /// # }
59 /// ```
60 ///
61 /// # Errors
62 ///
63 /// 1) `ItemNotFound`: If the storage denoted by storage_id does not exist
64 /// or if the object identifier cannot be found in the storage.
65 /// 2) `Access_Conflict`: If an access right conflict was detected while
66 /// opening the object.
67 /// 3) `OutOfMemory`: If there is not enough memory to complete the
68 /// operation.
69 /// 4) `CorruptObject`: If the object is corrupt. The object handle SHALL
70 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
71 /// property.
72 /// 5) `StorageNotAvailable`: If the object is stored in a storage area
73 /// which is currently inaccessible.
74 ///
75 /// # Panics
76 ///
77 /// 1) If object_id.len() >
78 /// [MiscellaneousConstants::TeeObjectIdMaxLen](crate::MiscellaneousConstants::TeeObjectIdMaxLen)
79 /// 2) If the Implementation detects any other error associated with this
80 /// function which is not explicitly associated with a defined return
81 /// code for this function.
82 pub fn open(
83 storage_id: ObjectStorageConstants,
84 object_id: &[u8],
85 flags: DataFlag,
86 ) -> Result<Self> {
87 let mut handle: raw::TEE_ObjectHandle = core::ptr::null_mut();
88 // Move as much code as possible out of unsafe blocks to maximize Rust’s
89 // safety checks.
90 let handle_mut = &mut handle;
91 match unsafe {
92 raw::TEE_OpenPersistentObject(
93 storage_id as u32,
94 object_id.as_ptr() as _,
95 object_id.len(),
96 flags.bits(),
97 handle_mut,
98 )
99 } {
100 raw::TEE_SUCCESS => Ok(Self(ObjectHandle::from_raw(handle)?)),
101 code => Err(Error::from_raw_error(code)),
102 }
103 }
104
105 /// Create an object with initial attributes and an initial data stream
106 /// content.
107 ///
108 /// # Parameters
109 ///
110 /// 1) `storage_id`: The storage to use which is defined in
111 /// [ObjectStorageConstants](crate::ObjectStorageConstants).
112 /// 2) `object_id`: The object identifier. Note that this buffer cannot
113 /// reside in shared memory.
114 /// 3) `flags`: The [DataFlag](crate::DataFlag) which determine the settings
115 /// under which the object is opened.
116 /// 4) `attributes`: A handle on a
117 /// [PersistentObject](crate::PersistentObject) or an initialized
118 /// [TransientObject](crate::TransientObject) from which to take the
119 /// [PersistentObject](crate::PersistentObject) attributes.
120 /// Can be NONE if the [PersistentObject](crate::PersistentObject)
121 /// contains no attribute. For example,if it is a pure data object.
122 ///
123 /// # Example
124 ///
125 /// ``` rust,no_run
126 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
127 /// # fn main() -> optee_utee::Result<()> {
128 /// let obj_id = [1u8;1];
129 /// let mut init_data: [u8; 0] = [0; 0];
130 /// match PersistentObject::create(
131 /// ObjectStorageConstants::Private,
132 /// &obj_id,
133 /// DataFlag::ACCESS_READ | DataFlag::ACCESS_WRITE,
134 /// None,
135 /// &mut init_data) {
136 /// Ok(object) =>
137 /// {
138 /// // ...
139 /// Ok(())
140 /// }
141 /// Err(e) => Err(e),
142 /// }
143 /// # }
144 /// ```
145 ///
146 /// # Errors
147 ///
148 /// 1) `ItemNotFound`: If the storage denoted by storage_id does not exist.
149 /// 2) `Access_Conflict`: If an access right conflict was detected while
150 /// opening the object.
151 /// 3) `OutOfMemory`: If there is not enough memory to complete the
152 /// operation.
153 /// 4) `StorageNoSpace`: If insufficient space is available to create the
154 /// persistent object.
155 /// 5) `CorruptObject`: If the storage is corrupt.
156 /// 6) `StorageNotAvailable`: If the object is stored in a storage area
157 /// which is currently inaccessible.
158 ///
159 /// # Panics
160 ///
161 /// 1) If object_id.len() >
162 /// [MiscellaneousConstants::TeeObjectIdMaxLen](crate::MiscellaneousConstants::TeeObjectIdMaxLen).
163 /// 2) If attributes is not NONE and is not a valid handle on an initialized
164 /// object containing the type and attributes of the object to create.
165 /// 3) If the Implementation detects any other error associated with this
166 /// function which is not explicitly associated with a defined return
167 /// code for this function.
168 pub fn create(
169 storage_id: ObjectStorageConstants,
170 object_id: &[u8],
171 flags: DataFlag,
172 attributes: Option<ObjectHandle>,
173 initial_data: &[u8],
174 ) -> Result<Self> {
175 let mut handle: raw::TEE_ObjectHandle = core::ptr::null_mut();
176 // Move as much code as possible out of unsafe blocks to maximize Rust’s
177 // safety checks.
178 let handle_mut = &mut handle;
179 let attributes = match attributes.as_ref() {
180 Some(a) => unsafe { *a.as_raw_ref() },
181 None => core::ptr::null_mut(),
182 };
183 match unsafe {
184 raw::TEE_CreatePersistentObject(
185 storage_id as u32,
186 object_id.as_ptr() as _,
187 object_id.len(),
188 flags.bits(),
189 attributes,
190 initial_data.as_ptr() as _,
191 initial_data.len(),
192 handle_mut,
193 )
194 } {
195 raw::TEE_SUCCESS => Ok(Self(ObjectHandle::from_raw(handle)?)),
196 code => Err(Error::from_raw_error(code)),
197 }
198 }
199
200 /// Marks an object for deletion and closes the object.
201 ///
202 /// # Example
203 ///
204 /// ``` rust,no_run
205 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
206 /// # fn main() -> optee_utee::Result<()> {
207 /// let obj_id = [1u8;1];
208 /// match PersistentObject::open (
209 /// ObjectStorageConstants::Private,
210 /// &obj_id,
211 /// DataFlag::ACCESS_READ) {
212 /// Ok(mut object) =>
213 /// {
214 /// object.close_and_delete()?;
215 /// Ok(())
216 /// }
217 /// Err(e) => Err(e),
218 /// }
219 /// # }
220 /// ```
221 ///
222 /// # Errors
223 ///
224 /// 1) `StorageNotAvailable`: If the object is stored in a storage area
225 /// which is currently inaccessible.
226 ///
227 /// # Panics
228 ///
229 /// 1) If object is not a valid opened object.
230 /// 2) If the Implementation detects any other error associated with this
231 /// function which is not explicitly associated with a defined return
232 /// code for this function.
233 ///
234 /// # Breaking Changes
235 ///
236 /// Now we no longer need to call `core::mem::forget` after successfully calling
237 /// `close_and_delete`, and code like this will now produce a compilation error.
238 /// ``` rust,compile_fail
239 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
240 /// # fn main() -> optee_utee::Result<()> {
241 /// # let obj_id = [0_u8];
242 /// let mut obj = PersistentObject::open (
243 /// ObjectStorageConstants::Private,
244 /// &obj_id,
245 /// DataFlag::ACCESS_READ,
246 /// )?;
247 /// obj.close_and_delete()?;
248 /// core::mem::forget(obj); // will get compilation error in this line
249 /// // ^^^ value used here after move
250 /// # Ok(())
251 /// # }
252 pub fn close_and_delete(self) -> Result<()> {
253 let result = match unsafe { raw::TEE_CloseAndDeletePersistentObject1(*self.as_raw_ref()) } {
254 raw::TEE_SUCCESS => Ok(()),
255 code => Err(Error::from_raw_error(code)),
256 };
257 // According to `GPD_TEE_Internal_Core_API_Specification_v1.3.1`:
258 // At 5.7.4 TEE_CloseAndDeletePersistentObject1:
259 // Deleting an object is atomic; once this function returns, the object
260 // is definitely deleted and no more open handles for the object exist.
261 //
262 // So we must forget the raw_handle to prevent calling TEE_CloseObject
263 // on it (no matter the result of TEE_CloseAndDeletePersistentObject1).
264 self.0.forget();
265 result
266 }
267
268 /// Changes the identifier of an object.
269 /// The object SHALL have been opened with the
270 /// [DataFlag::ACCESS_WRITE_META](crate::DataFlag::ACCESS_WRITE_META) right,
271 /// which means access to the object is exclusive.
272 ///
273 /// # Example
274 ///
275 /// ``` rust,no_run
276 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
277 /// # fn main() -> optee_utee::Result<()> {
278 /// let obj_id = [1u8;1];
279 /// let new_obj_id = [2u8;1];
280 /// match PersistentObject::open (
281 /// ObjectStorageConstants::Private,
282 /// &obj_id,
283 /// DataFlag::ACCESS_WRITE_META) {
284 /// Ok(mut object) =>
285 /// {
286 /// object.rename(&new_obj_id)?;
287 /// Ok(())
288 /// }
289 /// Err(e) => Err(e),
290 /// }
291 /// # }
292 /// ```
293 ///
294 /// # Errors
295 ///
296 /// 1) `AccessConflict`: If an object with the same identifier already
297 /// exists.
298 /// 2) `CorruptObject`: If the object is corrupt. The object handle SHALL
299 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
300 /// property.
301 /// 3) `StorageNotAvailable`: If the object is stored in a storage area
302 /// which is currently inaccessible.
303 ///
304 /// # Panics
305 ///
306 /// 1) If object is not a valid handle on a persistent object that has been
307 /// opened with the write-meta access right.
308 /// 2) If new_object_id resides in shared memory.
309 /// 3) If new_object_id.len() >
310 /// [MiscellaneousConstants::TeeObjectIdMaxLen](crate::MiscellaneousConstants::TeeObjectIdMaxLen).
311 /// 4) If the Implementation detects any other error associated with this
312 /// function which is not explicitly associated with a defined return
313 /// code for this function.
314 pub fn rename(&mut self, new_object_id: &[u8]) -> Result<()> {
315 match unsafe {
316 raw::TEE_RenamePersistentObject(
317 *self.0.as_raw_ref(),
318 new_object_id.as_ptr() as _,
319 new_object_id.len(),
320 )
321 } {
322 raw::TEE_SUCCESS => Ok(()),
323 code => Err(Error::from_raw_error(code)),
324 }
325 }
326
327 /// Read requested size from the data stream associate with the object into
328 /// the buffer.
329 ///
330 /// # Parameters
331 ///
332 /// 1) `buffer`: A pre-allocated buffer for saving the object's data stream.
333 /// 2) `count`: The returned value contains the number of bytes read.
334 /// # Example
335 ///
336 /// ``` rust,no_run
337 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
338 /// # fn main() -> optee_utee::Result<()> {
339 /// let obj_id = [1u8;1];
340 /// match PersistentObject::open (
341 /// ObjectStorageConstants::Private,
342 /// &obj_id,
343 /// DataFlag::ACCESS_READ) {
344 /// Ok(mut object) =>
345 /// {
346 /// let mut read_buf = [0u8;16];
347 /// object.read(&mut read_buf)?;
348 /// Ok(())
349 /// }
350 /// Err(e) => Err(e),
351 /// }
352 /// # }
353 /// ```
354 ///
355 /// # Errors
356 ///
357 /// 1) `CorruptObject`: If the object is corrupt. The object handle SHALL
358 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
359 /// property.
360 /// 2) `StorageNotAvailable`: If the object is stored in a storage area
361 /// which is currently inaccessible.
362 ///
363 /// # Panics
364 ///
365 /// 1) If object is not a valid handle on a persistent object opened with
366 /// the read access right.
367 /// 2) If the Implementation detects any other error associated with this
368 /// function which is not explicitly associated with a defined return
369 /// code for this function.
370 pub fn read(&mut self, buf: &mut [u8]) -> Result<u32> {
371 let mut count: usize = 0;
372 match unsafe {
373 raw::TEE_ReadObjectData(
374 *self.as_raw_ref(),
375 buf.as_mut_ptr() as _,
376 buf.len(),
377 &mut count,
378 )
379 } {
380 raw::TEE_SUCCESS => Ok(count as u32),
381 code => Err(Error::from_raw_error(code)),
382 }
383 }
384
385 /// Write the passed in buffer data into from the data stream associate with
386 /// the object.
387 ///
388 /// # Parameters
389 ///
390 /// 1) `buffer`: A pre-allocated buffer for saving the object's data stream.
391 ///
392 /// # Example
393 ///
394 /// ``` rust,no_run
395 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
396 /// # fn main() -> optee_utee::Result<()> {
397 /// let obj_id = [1u8;1];
398 /// match PersistentObject::open (
399 /// ObjectStorageConstants::Private,
400 /// &obj_id,
401 /// DataFlag::ACCESS_WRITE) {
402 /// Ok(mut object) =>
403 /// {
404 /// let write_buf = [1u8;16];
405 /// object.write(& write_buf)?;
406 /// Ok(())
407 /// }
408 /// Err(e) => Err(e),
409 /// }
410 /// # }
411 /// ```
412 ///
413 /// # Errors
414 ///
415 /// 1) `StorageNoSpace`: If insufficient storage space is available.
416 /// 2) `Overflow`: If the value of the data position indicator resulting
417 /// from this operation would be greater than
418 /// [MiscellaneousConstants::TeeDataMaxPosition](crate::MiscellaneousConstants::TeeDataMaxPosition).
419 /// 3) `CorruptObject`: If the object is corrupt. The object handle SHALL
420 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
421 /// property.
422 /// 4) `StorageNotAvailable`: If the object is stored in a storage area
423 /// which is currently inaccessible.
424 ///
425 /// # Panics
426 ///
427 /// 1) If object is not a valid handle on a persistent object opened with
428 /// the write access right
429 /// 2) If the Implementation detects any other error associated with this
430 /// function which is not explicitly associated with a defined return
431 /// code for this function.
432 pub fn write(&mut self, buf: &[u8]) -> Result<()> {
433 match unsafe { raw::TEE_WriteObjectData(*self.as_raw_ref(), buf.as_ptr() as _, buf.len()) }
434 {
435 raw::TEE_SUCCESS => Ok(()),
436 code => Err(Error::from_raw_error(code)),
437 }
438 }
439
440 /// Change the size of a data stream associate with the object.
441 ///
442 /// # Example
443 ///
444 /// ``` rust,no_run
445 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag};
446 /// # fn main() -> optee_utee::Result<()> {
447 /// let obj_id = [1u8;1];
448 /// match PersistentObject::open (
449 /// ObjectStorageConstants::Private,
450 /// &obj_id,
451 /// DataFlag::ACCESS_WRITE) {
452 /// Ok(mut object) =>
453 /// {
454 /// object.truncate(1u32)?;
455 /// Ok(())
456 /// }
457 /// Err(e) => Err(e),
458 /// }
459 /// # }
460 /// ```
461 ///
462 /// # Errors
463 ///
464 /// 1) `StorageNoSpace`: If insufficient storage space is available.
465 /// 2) `CorruptObject`: If the object is corrupt. The object handle SHALL
466 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
467 /// property.
468 /// 3) `StorageNotAvailable`: If the object is stored in a storage area
469 /// which is currently inaccessible.
470 ///
471 /// # Panics
472 ///
473 /// 1) If object is not a valid handle on a persistent object opened with
474 /// the write access right.
475 /// 2) If the Implementation detects any other error associated with this
476 /// function which is not explicitly associated with a defined return
477 /// code for this function.
478 pub fn truncate(&mut self, size: u32) -> Result<()> {
479 match unsafe { raw::TEE_TruncateObjectData(*self.as_raw_ref(), size as usize) } {
480 raw::TEE_SUCCESS => Ok(()),
481 code => Err(Error::from_raw_error(code)),
482 }
483 }
484
485 /// Set the data position indicator associate with the object.
486 ///
487 /// # Parameters
488 /// 1) `whence`: Defined in [Whence](crate::Whence).
489 /// 2) `offset`: The bytes shifted based on `whence`.
490 ///
491 /// # Example
492 ///
493 /// ``` rust,no_run
494 /// # use optee_utee::{PersistentObject, ObjectStorageConstants, DataFlag, Whence};
495 /// # fn main() -> optee_utee::Result<()> {
496 /// let obj_id = [1u8;1];
497 /// match PersistentObject::open(
498 /// ObjectStorageConstants::Private,
499 /// &obj_id,
500 /// DataFlag::ACCESS_WRITE) {
501 /// Ok(mut object) =>
502 /// {
503 /// object.seek(0i32, Whence::DataSeekSet)?;
504 /// Ok(())
505 /// }
506 /// Err(e) => Err(e),
507 /// }
508 /// # }
509 /// ```
510 ///
511 /// # Errors
512 ///
513 /// 1) `Overflow`: If data position indicator is greater than
514 /// [MiscellaneousConstants::TeeDataMaxPosition](crate::MiscellaneousConstants::TeeDataMaxPosition).
515 /// 2) `CorruptObject`: If the object is corrupt. The object handle SHALL
516 /// behave based on the `gpd.ta.doesNotCloseHandleOnCorruptObject`
517 /// property.
518 /// 3) `StorageNotAvailable`: If the object is stored in a storage area
519 /// which is currently inaccessible.
520 ///
521 /// # Panics
522 ///
523 /// 1) If object is not a valid handle on a persistent object.
524 /// 2) If the Implementation detects any other error associated with this
525 /// function which is not explicitly associated with a defined return
526 /// code for this function.
527 pub fn seek(&mut self, offset: i32, whence: Whence) -> Result<()> {
528 match unsafe { raw::TEE_SeekObjectData(*self.as_raw_ref(), offset.into(), whence.into()) } {
529 raw::TEE_SUCCESS => Ok(()),
530 code => Err(Error::from_raw_error(code)),
531 }
532 }
533}
534
535impl GenericObject for PersistentObject {
536 unsafe fn as_raw_ref(&self) -> &optee_utee_sys::TEE_ObjectHandle {
537 unsafe { self.0.as_raw_ref() }
538 }
539}
540
541#[cfg(test)]
542mod tests {
543 extern crate std;
544
545 use optee_utee_sys::{
546 mock_api,
547 mock_utils::{SERIAL_TEST_LOCK, object::MockHandle},
548 };
549
550 use super::*;
551
552 #[test]
553 // If a persistent object is successfully created, TEE_CloseObject will be
554 // called when it is dropped.
555 fn test_create_and_drop() {
556 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
557
558 let mut raw_handle = MockHandle::new();
559 let handle = raw_handle.as_handle();
560 let fn1 = mock_api::TEE_CreatePersistentObject_context();
561 let fn2 = mock_api::TEE_CloseObject_context();
562
563 fn1.expect()
564 .return_once_st(move |_, _, _, _, _, _, _, obj| {
565 unsafe { *obj = handle.clone() };
566 raw::TEE_SUCCESS
567 });
568 fn2.expect().return_once_st(move |obj| {
569 debug_assert_eq!(obj, handle);
570 });
571
572 let _obj = PersistentObject::create(
573 ObjectStorageConstants::Private,
574 &[],
575 DataFlag::ACCESS_WRITE,
576 None,
577 &[],
578 )
579 .expect("it should be ok");
580 }
581
582 #[test]
583 // https://github.com/apache/teaclave-trustzone-sdk/issues/288
584 fn test_create_with_attribute() {
585 use std::sync::{Arc, Mutex};
586
587 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
588
589 let mut raw_handle = MockHandle::new();
590 let mut attr_raw_handle = MockHandle::new();
591 let handle = raw_handle.as_handle();
592 let attr_handle = attr_raw_handle.as_handle();
593 let fn1 = mock_api::TEE_CreatePersistentObject_context();
594 let fn2 = mock_api::TEE_CloseObject_context();
595 let attribute_has_drop = Arc::new(Mutex::new(false));
596
597 fn1.expect().return_once_st({
598 let attribute_has_drop = attribute_has_drop.clone();
599 move |_, _, _, _, attr, _, _, obj| {
600 assert_eq!(attr, attr_handle);
601 let value: bool = *attribute_has_drop.lock().unwrap();
602 assert!(!value);
603 unsafe { *obj = handle.clone() };
604 raw::TEE_SUCCESS
605 }
606 });
607 fn2.expect()
608 .returning_st(move |obj| {
609 if obj == attr_handle {
610 let mut value = attribute_has_drop.lock().unwrap();
611 *value = true;
612 return;
613 }
614 assert_eq!(obj, handle);
615 })
616 .times(2);
617
618 let _obj = PersistentObject::create(
619 ObjectStorageConstants::Private,
620 &[],
621 DataFlag::ACCESS_WRITE,
622 Some(ObjectHandle::from_raw(attr_handle).unwrap()),
623 &[],
624 )
625 .expect("it should be ok");
626 }
627
628 #[test]
629 fn test_create_failed() {
630 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
631
632 static RETURN_CODE: raw::TEE_Result = raw::TEE_ERROR_BAD_STATE;
633 let fn1 = mock_api::TEE_CreatePersistentObject_context();
634
635 fn1.expect().return_const_st(RETURN_CODE);
636
637 let err = PersistentObject::create(
638 ObjectStorageConstants::Private,
639 &[],
640 DataFlag::ACCESS_WRITE,
641 None,
642 &[],
643 )
644 .expect_err("it should be err");
645
646 assert_eq!(err.raw_code(), RETURN_CODE);
647 }
648
649 #[test]
650 // If a persistent object successfully `close_and_delete`, it should not
651 // call `TEE_CloseObject` anymore.
652 fn test_create_and_successfully_close_delete() {
653 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
654
655 let mut raw_handle = MockHandle::new();
656 let handle = raw_handle.as_handle();
657 let fn1 = mock_api::TEE_CreatePersistentObject_context();
658 let fn2 = mock_api::TEE_CloseAndDeletePersistentObject1_context();
659
660 fn1.expect()
661 .return_once_st(move |_, _, _, _, _, _, _, obj| {
662 unsafe { *obj = handle.clone() };
663 raw::TEE_SUCCESS
664 });
665 fn2.expect().return_once_st(move |obj| {
666 debug_assert_eq!(obj, handle);
667 raw::TEE_SUCCESS
668 });
669
670 let obj = PersistentObject::create(
671 ObjectStorageConstants::Private,
672 &[],
673 DataFlag::ACCESS_WRITE,
674 None,
675 &[],
676 )
677 .expect("it should be ok");
678
679 obj.close_and_delete().expect("it should be ok");
680 }
681
682 #[test]
683 // Even a persistent object failed at `close_and_delete`, `TEE_CloseObject`
684 // should not be called.
685 fn test_create_and_failed_close_delete() {
686 let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
687
688 let mut raw_handle = MockHandle::new();
689 let handle = raw_handle.as_handle();
690 let fn1 = mock_api::TEE_CreatePersistentObject_context();
691 let fn2 = mock_api::TEE_CloseAndDeletePersistentObject1_context();
692
693 fn1.expect()
694 .return_once_st(move |_, _, _, _, _, _, _, obj| {
695 unsafe { *obj = handle.clone() };
696 raw::TEE_SUCCESS
697 });
698 fn2.expect().return_once_st(move |obj| {
699 debug_assert_eq!(obj, handle);
700 raw::TEE_ERROR_BUSY
701 });
702
703 let obj = PersistentObject::create(
704 ObjectStorageConstants::Private,
705 &[],
706 DataFlag::ACCESS_WRITE,
707 None,
708 &[],
709 )
710 .expect("it should be ok");
711
712 obj.close_and_delete().expect_err("it should be err");
713 }
714}