• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::bridge::ffi::BluetoothKeystoreInterface;
2 use crate::init_flags::AID_BLUETOOTH;
3 use cxx::UniquePtr;
4 use nix::unistd::getuid;
5 use std::marker::Send;
6 use std::ptr::null_mut;
7 use std::string::String;
8 use std::sync::Mutex;
9 
10 /// A single ParameterProvider
11 pub struct ParameterProvider {
12     configuration_file_path: String,
13     btsnoop_log_file_path: String,
14     btsnooz_log_file_path: String,
15     common_criteria_mode: bool,
16     common_criteria_config_compare_result: i32,
17     bt_keystore_interface: *mut BluetoothKeystoreInterface,
18     lock: Mutex<i32>,
19 }
20 
21 unsafe impl Send for ParameterProvider {}
22 unsafe impl Send for BluetoothKeystoreInterface {}
23 
24 impl ParameterProvider {
25     /// Construct a new ParameterProvider
new(prefix: String) -> Self26     pub fn new(prefix: String) -> Self {
27         Self {
28             configuration_file_path: prefix.clone() + "bluedroid/bt_config.conf",
29             btsnoop_log_file_path: prefix.clone() + "bluetooth/logs/btsnoop_hci.log",
30             btsnooz_log_file_path: prefix + "bluetooth/logs/btsnooz_hci.log",
31             common_criteria_mode: false,
32             common_criteria_config_compare_result: 0b11,
33             bt_keystore_interface: null_mut(),
34             lock: Mutex::new(0),
35         }
36     }
37 
38     /// Get the config file path
config_file_path(&self) -> String39     pub async fn config_file_path(&self) -> String {
40         let guard = self.lock.lock().unwrap();
41         let path = &self.configuration_file_path;
42         drop(guard);
43         path.to_string()
44     }
45 
46     /// Set the config file path
override_config_file_path(&mut self, path: &str)47     pub async fn override_config_file_path(&mut self, path: &str) {
48         let guard = self.lock.lock().unwrap();
49         self.configuration_file_path = path.to_string();
50         drop(guard);
51     }
52 
53     /// Get the snoop file path
snoop_log_file_path(&mut self) -> String54     pub async fn snoop_log_file_path(&mut self) -> String {
55         let guard = self.lock.lock().unwrap();
56         let path = &self.btsnoop_log_file_path;
57         drop(guard);
58         path.to_string()
59     }
60 
61     /// Set the snoop file path
override_snoop_file_path(&mut self, path: &str)62     pub async fn override_snoop_file_path(&mut self, path: &str) {
63         let guard = self.lock.lock().unwrap();
64         self.btsnoop_log_file_path = path.to_string();
65         drop(guard);
66     }
67 
68     /// Get the snooz log file path
snooz_log_file_path(&mut self) -> String69     pub async fn snooz_log_file_path(&mut self) -> String {
70         let guard = self.lock.lock().unwrap();
71         let path = &self.btsnooz_log_file_path;
72         drop(guard);
73         path.to_string()
74     }
75 
76     /// Set the snooz file path
override_snooz_file_path(&mut self, path: &str)77     pub async fn override_snooz_file_path(&mut self, path: &str) {
78         let guard = self.lock.lock().unwrap();
79         self.btsnooz_log_file_path = path.to_string();
80         drop(guard);
81     }
82 
83     /// Get the bluetooth keystore interface
get_bt_keystore_interface(&mut self) -> *mut BluetoothKeystoreInterface84     pub async fn get_bt_keystore_interface(&mut self) -> *mut BluetoothKeystoreInterface {
85         let guard = self.lock.lock().unwrap();
86         let result = &self.bt_keystore_interface;
87         drop(guard);
88         *result
89     }
90 
91     /// Set the bluetooth keystore interface
set_bt_keystore_interface( &mut self, by_keystore: UniquePtr<BluetoothKeystoreInterface>, )92     pub async fn set_bt_keystore_interface(
93         &mut self,
94         by_keystore: UniquePtr<BluetoothKeystoreInterface>,
95     ) {
96         let guard = self.lock.lock().unwrap();
97         self.bt_keystore_interface = by_keystore.into_raw();
98         drop(guard);
99     }
100 
101     /// Get the common criteria mode
is_common_criteria_mode(&self) -> bool102     pub async fn is_common_criteria_mode(&self) -> bool {
103         let guard = self.lock.lock().unwrap();
104         let enable = &self.common_criteria_mode;
105         drop(guard);
106         return (getuid().as_raw() == *(*AID_BLUETOOTH).lock().unwrap()) && *enable;
107     }
108 
109     /// Set the common criteria mode
set_common_criteria_mode(&mut self, enable: bool)110     pub async fn set_common_criteria_mode(&mut self, enable: bool) {
111         let guard = self.lock.lock().unwrap();
112         self.common_criteria_mode = enable;
113         drop(guard);
114     }
115 
116     /// Get the common criteria config compare result
get_common_criteria_config_compare_result(&self) -> i32117     pub async fn get_common_criteria_config_compare_result(&self) -> i32 {
118         let guard = self.lock.lock().unwrap();
119         let result = &self.common_criteria_config_compare_result;
120         drop(guard);
121         *result
122     }
123 
124     /// Set the common criteria config compare result
set_common_criteria_config_compare_result(&mut self, result: i32)125     pub async fn set_common_criteria_config_compare_result(&mut self, result: i32) {
126         let guard = self.lock.lock().unwrap();
127         self.common_criteria_config_compare_result = result;
128         drop(guard);
129     }
130 }
131 
132 #[cfg(test)]
133 mod tests {
134     use crate::bridge::ffi;
135     use crate::bridge::ffi::BluetoothKeystoreInterface;
136     use crate::bridge::ParameterProvider;
137     use crate::init_flags::AID_BLUETOOTH;
138     use crate::init_flags::MISC;
139     use nix::unistd::getuid;
140     use std::assert_eq;
141     use std::i64;
142     use std::ptr::null_mut;
143     use std::sync::atomic::{AtomicBool, Ordering};
144     use std::sync::Arc;
145     use tokio::sync::Mutex;
146 
147     #[tokio::test]
test_config_file_path()148     async fn test_config_file_path() {
149         let prefix: String = (*(*MISC).lock().unwrap()).clone();
150         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
151         let origin: String = (*param_provider.lock().await).config_file_path().await;
152         assert_eq!(origin, "/data/misc/bluedroid/bt_config.conf");
153         let choice = Arc::new(Mutex::new("0"));
154 
155         for i in 1..3 {
156             let select = Arc::clone(&choice);
157             let param_provider_cur = Arc::clone(&param_provider);
158 
159             tokio::spawn(async move {
160                 let mut c = select.lock().await;
161                 if i == 1 {
162                     *c = "1";
163                     param_provider_cur.lock().await.override_config_file_path(&c.to_string()).await;
164                 } else {
165                     *c = "2";
166                     param_provider_cur.lock().await.override_config_file_path(&c.to_string()).await;
167                 }
168             })
169             .await
170             .unwrap();
171         }
172 
173         let current: String = (*param_provider.lock().await).config_file_path().await;
174         assert_eq!(*choice.lock().await, &current);
175         (*param_provider.lock().await).override_config_file_path(&origin).await;
176         let now: String = (*param_provider.lock().await).config_file_path().await;
177         assert_eq!(now, "/data/misc/bluedroid/bt_config.conf");
178     }
179 
180     #[tokio::test]
test_snoop_log_file_path()181     async fn test_snoop_log_file_path() {
182         let prefix: String = (*(*MISC).lock().unwrap()).clone();
183         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
184         let origin: String = (*param_provider.lock().await).snoop_log_file_path().await;
185         assert_eq!(origin, "/data/misc/bluetooth/logs/btsnoop_hci.log");
186         let choice = Arc::new(Mutex::new("0"));
187 
188         for i in 1..3 {
189             let select = Arc::clone(&choice);
190             let param_provider_cur = Arc::clone(&param_provider);
191 
192             tokio::spawn(async move {
193                 let mut c = select.lock().await;
194                 if i == 1 {
195                     *c = "1";
196                     param_provider_cur.lock().await.override_snoop_file_path(&c.to_string()).await;
197                 } else {
198                     *c = "2";
199                     param_provider_cur.lock().await.override_snoop_file_path(&c.to_string()).await;
200                 }
201             })
202             .await
203             .unwrap();
204         }
205 
206         let current: String = (*param_provider.lock().await).snoop_log_file_path().await;
207         assert_eq!(*choice.lock().await, &current);
208         (*param_provider.lock().await).override_snoop_file_path(&origin).await;
209         let now: String = (*param_provider.lock().await).snoop_log_file_path().await;
210         assert_eq!(now, "/data/misc/bluetooth/logs/btsnoop_hci.log");
211     }
212 
213     #[tokio::test]
test_snooz_log_file_path()214     async fn test_snooz_log_file_path() {
215         let prefix: String = (*(*MISC).lock().unwrap()).clone();
216         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
217         let origin: String = (*param_provider.lock().await).snooz_log_file_path().await;
218         assert_eq!(origin, "/data/misc/bluetooth/logs/btsnooz_hci.log");
219         let choice = Arc::new(Mutex::new("0"));
220 
221         for i in 1..3 {
222             let select = Arc::clone(&choice);
223             let param_provider_cur = Arc::clone(&param_provider);
224 
225             tokio::spawn(async move {
226                 let mut c = select.lock().await;
227                 if i == 1 {
228                     *c = "1";
229                     param_provider_cur.lock().await.override_snooz_file_path(&c.to_string()).await;
230                 } else {
231                     *c = "2";
232                     param_provider_cur.lock().await.override_snooz_file_path(&c.to_string()).await;
233                 }
234             })
235             .await
236             .unwrap();
237         }
238 
239         let current: String = (*param_provider.lock().await).snooz_log_file_path().await;
240         assert_eq!(*choice.lock().await, &current);
241         (*param_provider.lock().await).override_snooz_file_path(&origin).await;
242         let now: String = (*param_provider.lock().await).snooz_log_file_path().await;
243         assert_eq!(now, "/data/misc/bluetooth/logs/btsnooz_hci.log");
244     }
245 
246     #[ignore]
247     #[tokio::test]
test_bt_keystore_interface()248     async fn test_bt_keystore_interface() {
249         let prefix: String = (*(*MISC).lock().unwrap()).clone();
250         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
251         let origin: *mut BluetoothKeystoreInterface =
252             (*param_provider.lock().await).get_bt_keystore_interface().await;
253         assert_eq!(origin, null_mut());
254 
255         let choice_ptr1: cxx::UniquePtr<ffi::BluetoothKeystoreInterface> =
256             ffi::new_bt_keystore_interface();
257         let address1 = Arc::new(Mutex::new(format!("{:p}", &choice_ptr1)));
258 
259         let choice_ptr2: cxx::UniquePtr<ffi::BluetoothKeystoreInterface> =
260             ffi::new_bt_keystore_interface();
261         let address2 = Arc::new(Mutex::new(format!("{:p}", &choice_ptr2)));
262 
263         let choice = Arc::new(Mutex::new("0"));
264 
265         for i in 1..3 {
266             let select = Arc::clone(&choice);
267             let param_provider_cur = Arc::clone(&param_provider);
268             let addr1 = Arc::clone(&address1);
269             let addr2 = Arc::clone(&address2);
270 
271             tokio::spawn(async move {
272                 let mut c = select.lock().await;
273                 let mut a1 = addr1.lock().await;
274                 let mut a2 = addr2.lock().await;
275 
276                 if i == 1 {
277                     let ptr1: cxx::UniquePtr<ffi::BluetoothKeystoreInterface> =
278                         ffi::new_bt_keystore_interface();
279                     *c = "1";
280                     *a1 = format!("{:p}", &ptr1);
281                     param_provider_cur.lock().await.set_bt_keystore_interface(ptr1).await;
282                 } else {
283                     let ptr2: cxx::UniquePtr<ffi::BluetoothKeystoreInterface> =
284                         ffi::new_bt_keystore_interface();
285                     *c = "2";
286                     *a2 = format!("{:p}", &ptr2);
287                     param_provider_cur.lock().await.set_bt_keystore_interface(ptr2).await;
288                 }
289             })
290             .await
291             .unwrap();
292         }
293 
294         let current = (*param_provider.lock().await).get_bt_keystore_interface().await;
295         let address_current = format!("{:p}", &current);
296         let reality = *hex_to_dec(address_current);
297         let mut answer = *hex_to_dec(Arc::clone(&address1).lock().await.to_string());
298         if *choice.lock().await == "2" {
299             answer = *hex_to_dec(Arc::clone(&address2).lock().await.to_string());
300         }
301         assert_eq!(reality, answer);
302     }
303 
304     #[tokio::test]
test_common_criteria_mode()305     async fn test_common_criteria_mode() {
306         let prefix: String = (*(*MISC).lock().unwrap()).clone();
307         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
308         let origin: bool = (*param_provider.lock().await).is_common_criteria_mode().await;
309         assert!(!origin);
310 
311         let choice = Arc::new(AtomicBool::new(false));
312 
313         let init_bt: u32 = *(*AID_BLUETOOTH).lock().unwrap();
314         *(*AID_BLUETOOTH).lock().unwrap() = getuid().as_raw();
315 
316         for i in 1..3 {
317             let select = Arc::clone(&choice);
318             let param_provider_cur = Arc::clone(&param_provider);
319 
320             tokio::spawn(async move {
321                 if i == 1 {
322                     select.store(true, Ordering::Relaxed);
323                     param_provider_cur.lock().await.set_common_criteria_mode(true).await;
324                 } else {
325                     select.store(false, Ordering::Relaxed);
326                     param_provider_cur.lock().await.set_common_criteria_mode(false).await;
327                 }
328             })
329             .await
330             .unwrap();
331         }
332 
333         let current: bool = (*param_provider.lock().await).is_common_criteria_mode().await;
334         assert_eq!(choice.load(Ordering::SeqCst), current);
335         (*param_provider.lock().await).set_common_criteria_mode(origin).await;
336         let now: bool = (*param_provider.lock().await).is_common_criteria_mode().await;
337         assert!(!now);
338         *(*AID_BLUETOOTH).lock().unwrap() = init_bt;
339     }
340 
341     #[tokio::test]
test_common_criteria_config_compare_result()342     async fn test_common_criteria_config_compare_result() {
343         let prefix: String = (*(*MISC).lock().unwrap()).clone();
344         let param_provider = Arc::new(Mutex::new(ParameterProvider::new(prefix)));
345         let origin: i32 =
346             (*param_provider.lock().await).get_common_criteria_config_compare_result().await;
347         assert_eq!(origin, 0b11);
348         let counter = Arc::new(Mutex::new(0));
349 
350         for i in 1..3 {
351             let select = Arc::clone(&counter);
352             let param_provider_cur = Arc::clone(&param_provider);
353 
354             tokio::spawn(async move {
355                 let mut c = select.lock().await;
356                 if i == 1 {
357                     *c = 1;
358                     param_provider_cur
359                         .lock()
360                         .await
361                         .set_common_criteria_config_compare_result(*c)
362                         .await;
363                 } else {
364                     *c = 2;
365                     param_provider_cur
366                         .lock()
367                         .await
368                         .set_common_criteria_config_compare_result(*c)
369                         .await;
370                 }
371             })
372             .await
373             .unwrap();
374         }
375 
376         let current: i32 =
377             (*param_provider.lock().await).get_common_criteria_config_compare_result().await;
378         assert_eq!(*counter.lock().await, current);
379         (*param_provider.lock().await).set_common_criteria_config_compare_result(origin).await;
380         let now: i32 =
381             (*param_provider.lock().await).get_common_criteria_config_compare_result().await;
382         assert_eq!(now, 0b11);
383     }
384 
hex_to_dec(origin: String) -> &'static i64385     fn hex_to_dec(origin: String) -> &'static i64 {
386         let address = unsafe {
387             let origin = origin.trim_start_matches("0x");
388             &*(usize::from_str_radix(origin, 16).unwrap() as *const i64)
389         };
390         address
391     }
392 }
393