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}