diff --git a/linux-rust/src/bluetooth/le.rs b/linux-rust/src/bluetooth/le.rs index e51f52f..d4303b5 100644 --- a/linux-rust/src/bluetooth/le.rs +++ b/linux-rust/src/bluetooth/le.rs @@ -1,7 +1,7 @@ use bluer::monitor::{Monitor, MonitorEvent, Pattern, RssiSamplingPeriod}; use bluer::{Address, Session}; use aes::Aes128; -use aes::cipher::{BlockEncrypt, KeyInit}; +use aes::cipher::{BlockEncrypt, KeyInit, BlockDecrypt}; use aes::cipher::generic_array::GenericArray; use std::collections::{HashMap, HashSet}; use log::{info, error, debug}; @@ -31,6 +31,13 @@ fn e(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { result } +fn decrypt(key: &[u8; 16], data: &[u8; 16]) -> [u8; 16] { + let cipher = Aes128::new(&GenericArray::from(*key)); + let mut block = GenericArray::from(*data); + cipher.decrypt_block(&mut block); + block.into() +} + fn ah(k: &[u8; 16], r: &[u8; 3]) -> [u8; 3] { let mut r_padded = [0u8; 16]; r_padded[..3].copy_from_slice(r); @@ -55,6 +62,7 @@ fn verify_rpa(addr: &str, irk: &[u8; 16]) -> bool { let hash_slice = &rpa[0..3]; let hash: [u8; 3] = hash_slice.try_into().unwrap(); let computed_hash = ah(irk, &prand); + debug!("Verifying RPA: addr={}, hash={:?}, computed_hash={:?}", addr, hash, computed_hash); hash == computed_hash } @@ -69,6 +77,8 @@ pub async fn start_le_monitor() -> bluer::Result<()> { .unwrap_or_default(); let irk = proximity_keys.get(&ProximityKeyType::Irk) .and_then(|v| if v.len() == 16 { Some(<[u8; 16]>::try_from(v.as_slice()).unwrap()) } else { None }); + let enc_key = proximity_keys.get(&ProximityKeyType::EncKey) + .and_then(|v| if v.len() == 16 { Some(<[u8; 16]>::try_from(v.as_slice()).unwrap()) } else { None }); let mut verified_macs: HashSet
= HashSet::new(); let pattern = Pattern { @@ -85,23 +95,30 @@ pub async fn start_le_monitor() -> bluer::Result<()> { rssi_high_threshold: None, rssi_low_timeout: None, rssi_high_timeout: None, - rssi_sampling_period: Some(RssiSamplingPeriod::Period(Duration::from_millis(500))), + rssi_sampling_period: Some(RssiSamplingPeriod::Period(Duration::from_millis(100))), patterns: Some(vec![pattern]), ..Default::default() }) .await?; + debug!("Started LE monitor"); + while let Some(mevt) = monitor_handle.next().await { if let MonitorEvent::DeviceFound(devid) = mevt { let dev = adapter.device(devid.device)?; let addr = dev.address(); let addr_str = addr.to_string(); + debug!("Found device: {}", addr_str); + if !verified_macs.contains(&addr) { + debug!("Checking RPA for device: {}", addr_str); if let Some(irk) = &irk { if verify_rpa(&addr_str, irk) { verified_macs.insert(addr); - info!("matched our device ({}) with the irk", addr); + info!("Matched our device ({}) with the irk", addr); + } else { + debug!("Device {} did not match our irk", addr); } } } @@ -114,7 +131,53 @@ pub async fn start_le_monitor() -> bluer::Result<()> { bluer::DeviceEvent::PropertyChanged(prop) => { match prop { bluer::DeviceProperty::ManufacturerData(data) => { - info!("Manufacturer data from {}: {:?}", addr_str, data.iter().map(|(k, v)| (k, hex::encode(v))).collect::