Skip to main content

optee_utee_mock/
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 std::cell::UnsafeCell;
19use std::ffi::c_void;
20use std::sync::{Arc, Mutex, RwLock};
21
22use crate::raw::{self, TEE_ObjectHandle, TEE_ObjectType, TEE_Result};
23
24static GLOBAL_OBJECT_MOCK: RwLock<Option<Box<dyn ObjectController + 'static>>> = RwLock::new(None);
25pub static SERIAL_TEST_LOCK: Mutex<()> = Mutex::new(());
26
27#[mockall::automock]
28// currently we just add functions that we need
29pub trait ObjectController: Send + Sync {
30    // Data and Key Storage API  - Generic Object Functions
31    fn TEE_CloseObject(&self, object: TEE_ObjectHandle);
32
33    /* Data and Key Storage API  - Transient Object Functions */
34    fn TEE_AllocateTransientObject(
35        &self,
36        objectType: TEE_ObjectType,
37        maxObjectSize: u32,
38        object: *mut TEE_ObjectHandle,
39    ) -> TEE_Result;
40
41    // Data and Key Storage API  - Persistent Object Functions
42    fn TEE_OpenPersistentObject(
43        &self,
44        storageID: u32,
45        objectID: *const c_void,
46        objectIDLen: usize,
47        flags: u32,
48        object: *mut TEE_ObjectHandle,
49    ) -> TEE_Result;
50    fn TEE_CreatePersistentObject(
51        &self,
52        storageID: u32,
53        objectID: *const c_void,
54        objectIDLen: usize,
55        flags: u32,
56        attributes: TEE_ObjectHandle,
57        initialData: *const c_void,
58        initialDataLen: usize,
59        object: *mut TEE_ObjectHandle,
60    ) -> TEE_Result;
61    fn TEE_CloseAndDeletePersistentObject1(&self, object: TEE_ObjectHandle) -> TEE_Result;
62}
63
64pub fn set_global_object_mock(mock: impl ObjectController + 'static) {
65    let mut value = GLOBAL_OBJECT_MOCK.write().unwrap();
66    value.replace(Box::new(mock));
67}
68
69fn with_global_object_mock<R, F: FnOnce(&dyn ObjectController) -> R>(f: F) -> R {
70    let mock = GLOBAL_OBJECT_MOCK.read().unwrap();
71    let borrow = mock.as_ref().expect("Global Object Mock Not Set");
72    f(borrow.as_ref())
73}
74
75macro_rules! forward_to_mock {
76    ($fn_name:ident($($param:ident: $ty:ty),*) -> $ret:ty) => {
77        #[no_mangle]
78        fn $fn_name($($param: $ty),*) -> $ret {
79            with_global_object_mock(|mock: &dyn ObjectController| {
80                mock.$fn_name($($param),*)
81            })
82        }
83    };
84}
85
86forward_to_mock!(TEE_CloseObject(object: TEE_ObjectHandle) -> ());
87
88forward_to_mock!(TEE_AllocateTransientObject(
89    objectType: TEE_ObjectType,
90    maxObjectSize: u32,
91    object: *mut TEE_ObjectHandle
92) -> TEE_Result);
93
94forward_to_mock!(TEE_OpenPersistentObject(
95    storageID: u32,
96    objectID: *const c_void,
97    objectIDLen: usize,
98    flags: u32,
99    object: *mut TEE_ObjectHandle
100) -> TEE_Result);
101forward_to_mock!(TEE_CreatePersistentObject(
102    storageID: u32,
103    objectID: *const c_void,
104    objectIDLen: usize,
105    flags: u32,
106    attributes: TEE_ObjectHandle,
107    initialData: *const c_void,
108    initialDataLen: usize,
109    object: *mut TEE_ObjectHandle
110) -> TEE_Result);
111forward_to_mock!(TEE_CloseAndDeletePersistentObject1(
112    object: TEE_ObjectHandle
113) -> TEE_Result);
114
115type ValidTestHandle = Arc<UnsafeCell<raw::TEE_ObjectHandle>>;
116
117impl MockObjectController {
118    pub fn new_valid_test_handle_struct() -> raw::__TEE_ObjectHandle {
119        unsafe { core::mem::zeroed() }
120    }
121    pub fn new_valid_test_handle(handle: &mut raw::__TEE_ObjectHandle) -> ValidTestHandle {
122        Arc::new(UnsafeCell::new(handle))
123    }
124
125    pub fn expect_TEE_AllocateTransientObject_success_once(&mut self, handle: ValidTestHandle) {
126        self.expect_TEE_AllocateTransientObject()
127            .return_once_st(move |_, _, obj| {
128                unsafe {
129                    *obj = *handle.get();
130                }
131                raw::TEE_SUCCESS
132            });
133    }
134    pub fn expect_TEE_AllocateTransientObject_fail_once(&mut self, code: raw::TEE_Result) {
135        self.expect_TEE_AllocateTransientObject()
136            .return_once_st(move |_, _, _| code);
137    }
138
139    pub fn expect_TEE_CreatePersistentObject_success_once(&mut self, handle: ValidTestHandle) {
140        self.expect_TEE_CreatePersistentObject()
141            .return_once_st(move |_, _, _, _, _, _, _, obj| {
142                unsafe {
143                    *obj = *handle.get();
144                }
145                raw::TEE_SUCCESS
146            });
147    }
148    pub fn expect_TEE_CreatePersistentObject_fail_once(&mut self, code: raw::TEE_Result) {
149        self.expect_TEE_CreatePersistentObject()
150            .return_once_st(move |_, _, _, _, _, _, _, _| code);
151    }
152
153    pub fn expect_TEE_OpenPersistentObject_success_once(&mut self, handle: ValidTestHandle) {
154        self.expect_TEE_OpenPersistentObject()
155            .return_once_st(move |_, _, _, _, obj| {
156                unsafe {
157                    *obj = *handle.get();
158                }
159                raw::TEE_SUCCESS
160            });
161    }
162    pub fn expect_TEE_OpenPersistentObject_fail_once(&mut self, code: raw::TEE_Result) {
163        self.expect_TEE_OpenPersistentObject()
164            .return_once_st(move |_, _, _, _, _| code);
165    }
166
167    pub fn expect_TEE_CloseAndDeletePersistentObject1_success_once(
168        &mut self,
169        exp_handle: ValidTestHandle,
170    ) {
171        self.expect_TEE_CloseAndDeletePersistentObject1()
172            .return_once_st(move |obj| {
173                assert_eq!(obj, unsafe { *exp_handle.get() });
174                raw::TEE_SUCCESS
175            });
176    }
177    pub fn expect_TEE_CloseAndDeletePersistentObject1_fail_once(&mut self, code: raw::TEE_Result) {
178        self.expect_TEE_CloseAndDeletePersistentObject1()
179            .return_once_st(move |_| code);
180    }
181
182    pub fn expect_TEE_CloseObject_once(&mut self, exp_handle: ValidTestHandle) {
183        self.expect_TEE_CloseObject().return_once_st(move |obj| {
184            assert_eq!(obj, unsafe { *exp_handle.get() });
185        });
186    }
187}
188
189#[cfg(test)]
190mod test {
191    use super::*;
192    use crate::raw;
193
194    #[test]
195    fn test_new_handle() {
196        let mut handle_struct1 = MockObjectController::new_valid_test_handle_struct();
197        let mut handle_struct2 = MockObjectController::new_valid_test_handle_struct();
198
199        let handle1 = MockObjectController::new_valid_test_handle(&mut handle_struct1);
200        let handle2 = MockObjectController::new_valid_test_handle(&mut handle_struct2);
201
202        assert_ne!(unsafe { *handle1.get() }, unsafe { *handle2.get() });
203
204        let handle3: ValidTestHandle = Arc::new(UnsafeCell::new(core::ptr::null_mut()));
205        let handle4: ValidTestHandle = Arc::new(UnsafeCell::new(core::ptr::null_mut()));
206        assert_eq!(unsafe { *handle3.get() }, unsafe { *handle4.get() });
207    }
208
209    #[test]
210    fn test_mock_usage() {
211        let mut handle_struct = MockObjectController::new_valid_test_handle_struct();
212        let handle = MockObjectController::new_valid_test_handle(&mut handle_struct);
213        let mut mock = MockObjectController::new();
214
215        mock.expect_TEE_OpenPersistentObject_success_once(handle.clone());
216        mock.expect_TEE_CloseAndDeletePersistentObject1_success_once(handle.clone());
217        mock.expect_TEE_CloseObject_once(handle.clone());
218
219        set_global_object_mock(mock);
220
221        let mut handle = core::ptr::null_mut();
222        let result =
223            unsafe { raw::TEE_OpenPersistentObject(0, core::ptr::null(), 0, 0, &mut handle) };
224        assert_eq!(result, raw::TEE_SUCCESS);
225
226        let result = unsafe { raw::TEE_CloseAndDeletePersistentObject1(handle) };
227        assert_eq!(result, raw::TEE_SUCCESS);
228
229        unsafe { raw::TEE_CloseObject(handle) };
230    }
231}