optee_utee/object/
object_handle.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::GenericObject;
21
22/// An opaque handle on an object.
23#[derive(Debug)]
24pub struct ObjectHandle(raw::TEE_ObjectHandle);
25
26impl ObjectHandle {
27    pub fn from_raw(raw: raw::TEE_ObjectHandle) -> crate::Result<ObjectHandle> {
28        if raw.is_null() {
29            return Err(crate::ErrorKind::BadParameters.into());
30        }
31        Ok(Self(raw))
32    }
33
34    /// Forget the inner handle to prevent a double-free, this function would be
35    /// called when the inner handle is(or will be) freed externally.
36    ///
37    /// Example:
38    /// ``` rust,no_run
39    /// # use optee_utee::ObjectHandle;
40    /// # use optee_utee_sys as raw;
41    /// # let external_handle: raw::TEE_ObjectHandle = core::ptr::null_mut();
42    /// # fn main() -> optee_utee::Result<()> {
43    /// # let external_handle = core::ptr::null_mut();
44    /// // `external_handle` is a handle that is constructed and controlled
45    /// // externally.
46    /// // `handle` is valid, and will call TEE_CloseObject on
47    /// // `external_handle` when it is dropping, which is not allowed
48    /// // as the `external_handle` is externally controlled.
49    /// let mut handle = ObjectHandle::from_raw(external_handle)?;
50    /// // ... Some operation
51    /// // forget the inner handle, so it won't call TEE_CloseObject on
52    /// // `external_handle`
53    /// handle.forget();
54    /// # Ok(())
55    /// # }
56    /// ```
57    pub fn forget(mut self) {
58        self.0 = core::ptr::null_mut();
59    }
60}
61
62// functions for internal usage
63impl ObjectHandle {
64    pub(crate) fn new_null() -> Self {
65        Self(core::ptr::null_mut())
66    }
67
68    pub(crate) fn is_null(&self) -> bool {
69        self.0.is_null()
70    }
71}
72
73impl Drop for ObjectHandle {
74    fn drop(&mut self) {
75        if !self.is_null() {
76            unsafe { raw::TEE_CloseObject(self.0) }
77        }
78    }
79}
80
81impl GenericObject for ObjectHandle {
82    unsafe fn as_raw_ref(&self) -> &raw::TEE_ObjectHandle {
83        &self.0
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    extern crate std;
90
91    use optee_utee_sys::{
92        mock_api,
93        mock_utils::{SERIAL_TEST_LOCK, object::MockHandle},
94    };
95
96    use super::*;
97
98    /// Ensures `ObjectHandle` can be safely constructed from a raw handle
99    /// and automatically calls `TEE_CloseObject` when dropped.
100    #[test]
101    fn test_from_raw() {
102        let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
103
104        let mut raw_handle = MockHandle::new();
105        let handle = raw_handle.as_handle();
106        let fn1 = mock_api::TEE_CloseObject_context();
107
108        fn1.expect().return_once_st(move |obj| {
109            debug_assert_eq!(obj, handle.clone());
110        });
111
112        let obj = ObjectHandle::from_raw(handle.clone()).expect("it should be ok");
113        assert_eq!(unsafe { *obj.as_raw_ref() }, handle);
114    }
115
116    /// Ensures `ObjectHandle` can call `forget` to prevent automatically
117    /// calls `TEE_CloseObject` when dropped.
118    #[test]
119    fn test_forget() {
120        let _lock = SERIAL_TEST_LOCK.lock().expect("should get the lock");
121
122        let mut raw_handle = MockHandle::new();
123        let handle = raw_handle.as_handle();
124
125        let obj = ObjectHandle::from_raw(handle.clone()).expect("it should be ok");
126        assert_eq!(unsafe { *obj.as_raw_ref() }, handle);
127
128        obj.forget();
129    }
130
131    #[test]
132    fn test_new_null() {
133        let obj = ObjectHandle::new_null();
134        assert!(obj.is_null());
135    }
136}