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(¶m_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, ¤t); 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(¶m_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, ¤t); 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(¶m_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, ¤t); 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(¶m_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}", ¤t); 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(¶m_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(¶m_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