summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2023-10-22 05:47:20 +0200
committerSven Gothel <[email protected]>2023-10-22 05:47:20 +0200
commit116ce8e5a4672b963a4b2bbb2054158a77f8417b (patch)
tree7f388682118553ba2b7e344b25d6a03cb63b0205 /src
parent701ed7e6dbebbc2118726f203ae576df73ea5e2d (diff)
Adapter Random Address (WIP): Add BTAdapter::setPrivacy() and intercepting new-IRK
FIXME: Passing a HCILEOwnAddressType other than PUBLIC for "LE set scan Param" after setPrivacy(true) via BTManager results in failure. TBD: Seems like the mngr API and HCI is not aligned or my adapter revolts.
Diffstat (limited to 'src')
-rw-r--r--src/direct_bt/BTAdapter.cpp65
-rw-r--r--src/direct_bt/BTManager.cpp8
2 files changed, 73 insertions, 0 deletions
diff --git a/src/direct_bt/BTAdapter.cpp b/src/direct_bt/BTAdapter.cpp
index 5dc5670d..3fd69ba3 100644
--- a/src/direct_bt/BTAdapter.cpp
+++ b/src/direct_bt/BTAdapter.cpp
@@ -30,6 +30,7 @@
#include <cstdio>
#include <algorithm>
+#include <random>
#include <jau/debug.hpp>
@@ -331,6 +332,7 @@ bool BTAdapter::enableListening(const bool enable) noexcept {
ok = mgmt->addMgmtEventCallback(dev_id, MgmtEvent::Opcode::PAIR_DEVICE_COMPLETE, jau::bind_member(this, &BTAdapter::mgmtEvPairDeviceCompleteMgmt)) && ok;
ok = mgmt->addMgmtEventCallback(dev_id, MgmtEvent::Opcode::NEW_LONG_TERM_KEY, jau::bind_member(this, &BTAdapter::mgmtEvNewLongTermKeyMgmt)) && ok;
ok = mgmt->addMgmtEventCallback(dev_id, MgmtEvent::Opcode::NEW_LINK_KEY, jau::bind_member(this, &BTAdapter::mgmtEvNewLinkKeyMgmt)) && ok;
+ ok = mgmt->addMgmtEventCallback(dev_id, MgmtEvent::Opcode::NEW_IRK, jau::bind_member(this, &BTAdapter::mgmtEvNewIdentityResolvingKeyMgmt)) && ok;
if( !ok ) {
ERR_PRINT("Could not add all required MgmtEventCallbacks to DBTManager: %s", toString().c_str());
@@ -381,6 +383,7 @@ BTAdapter::BTAdapter(const BTAdapter::ctor_cookie& cc, BTManagerRef mgmt_, Adapt
hci_uses_ext_scan( false ), hci_uses_ext_conn( false ), hci_uses_ext_adv( false ),
visibleAddressAndType( adapterInfo_.addressAndType ),
visibleMACType( HCILEOwnAddressType::PUBLIC ),
+ privacyIRK(),
dev_id( adapterInfo.dev_id ),
btRole ( BTRole::Master ),
hci( dev_id ),
@@ -623,6 +626,42 @@ bool BTAdapter::setPowered(const bool power_on) noexcept {
return power_on == isAdapterSettingBitSet(new_settings, AdapterSetting::POWERED);
}
+HCIStatusCode BTAdapter::setPrivacy(const bool enable) noexcept {
+ jau::uint128_t irk;
+ if( enable ) {
+ std::unique_ptr<std::random_device> rng_hw = std::make_unique<std::random_device>();
+ for(int i=0; i<4; ++i) {
+ std::uint32_t v = (*rng_hw)();
+ irk.data[4*i+0] = v & 0x000000ffu;
+ irk.data[4*i+1] = ( v & 0x0000ff00u ) >> 8;
+ irk.data[4*i+2] = ( v & 0x00ff0000u ) >> 16;
+ irk.data[4*i+3] = ( v & 0xff000000u ) >> 24;
+ }
+ } else {
+ irk.clear();
+ }
+ AdapterSetting settings = adapterInfo.getCurrentSettingMask();
+ HCIStatusCode res = mgmt->setPrivacy(dev_id, enable ? 0x01 : 0x00, irk, settings);
+ if( HCIStatusCode::SUCCESS == res ) {
+ if( enable ) {
+ // FIXME: Not working for LE set scan param etc ..
+ // TODO visibleAddressAndType = ???
+ // visibleMACType = HCILEOwnAddressType::RESOLVABLE_OR_RANDOM;
+ visibleMACType = HCILEOwnAddressType::RESOLVABLE_OR_PUBLIC;
+ // visibleMACType = HCILEOwnAddressType::RANDOM;
+ } else {
+ visibleAddressAndType = adapterInfo.addressAndType;
+ visibleMACType = HCILEOwnAddressType::PUBLIC;
+ privacyIRK.address = adapterInfo.addressAndType.address;
+ privacyIRK.address_type = adapterInfo.addressAndType.type;
+ privacyIRK.irk.clear();
+ }
+ }
+ const AdapterSetting new_settings = adapterInfo.setCurrentSettingMask(settings);
+ updateAdapterSettings(false /* off_thread */, new_settings, true /* sendEvent */, 0);
+ return res;
+}
+
HCIStatusCode BTAdapter::setSecureConnections(const bool enable) noexcept {
AdapterSetting settings = adapterInfo.getCurrentSettingMask();
if( isAdapterSettingBitSet(settings, AdapterSetting::POWERED) ) {
@@ -2336,6 +2375,32 @@ void BTAdapter::mgmtEvNewLinkKeyMgmt(const MgmtEvent& e) noexcept {
}
}
+void BTAdapter::mgmtEvNewIdentityResolvingKeyMgmt(const MgmtEvent& e) noexcept {
+ const MgmtEvtNewIdentityResolvingKey& event = *static_cast<const MgmtEvtNewIdentityResolvingKey *>(&e);
+ const EUI48& randomAddress = event.getRandomAddress();
+ const MgmtIdentityResolvingKeyInfo& irk = event.getIdentityResolvingKey();
+ if( adapterInfo.addressAndType.address == irk.address && adapterInfo.addressAndType.type == irk.address_type ) {
+ // setPrivacy ...
+ visibleAddressAndType.address = randomAddress;
+ visibleAddressAndType.type = BDAddressType::BDADDR_LE_RANDOM;
+ visibleMACType = HCILEOwnAddressType::RESOLVABLE_OR_RANDOM;
+ privacyIRK = irk;
+ WORDY_PRINT("BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Host Adapter: %s",
+ dev_id, event.toString().c_str());
+ } else {
+ BTDeviceRef device = findConnectedDevice(randomAddress, BDAddressType::BDADDR_UNDEFINED);
+ if( nullptr != device ) {
+ // TODO: Notify our remove BDDevice instance about the resolved address!
+ // TODO: Support Random Address resolution!
+ WORDY_PRINT("BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Device found (Resolvable not yet supported): %s, %s",
+ dev_id, event.toString().c_str(), device->toString().c_str());
+ } else {
+ WORDY_PRINT("BTAdapter::mgmt:NewIdentityResolvingKey(dev_id %d): Device not tracked: %s",
+ dev_id, event.toString().c_str());
+ }
+ }
+}
+
void BTAdapter::mgmtEvDeviceFoundHCI(const MgmtEvent& e) noexcept {
// COND_PRINT(debug_event, "BTAdapter:hci:DeviceFound(dev_id %d): %s", dev_id, e.toString().c_str());
const MgmtEvtDeviceFound &deviceFoundEvent = *static_cast<const MgmtEvtDeviceFound *>(&e);
diff --git a/src/direct_bt/BTManager.cpp b/src/direct_bt/BTManager.cpp
index 84520ada..5a44228a 100644
--- a/src/direct_bt/BTManager.cpp
+++ b/src/direct_bt/BTManager.cpp
@@ -724,6 +724,14 @@ std::vector<MgmtDefaultParam> BTManager::readDefaultSysParam(const uint16_t dev_
return std::vector<MgmtDefaultParam>();
}
+HCIStatusCode BTManager::setPrivacy(const uint16_t dev_id, const uint8_t privacy, const jau::uint128_t& irk, AdapterSetting& current_settings) noexcept {
+ MgmtSetPrivacyCmd req(dev_id, privacy, irk);
+ MgmtStatus res = handleCurrentSettingsReply(sendWithReply(req), current_settings);
+ DBG_PRINT("BTManager::setPrivacy[%d]: %s, result %s %s", dev_id,
+ req.toString().c_str(), to_string(res).c_str(), to_string(current_settings).c_str());
+ return to_HCIStatusCode( res );
+}
+
HCIStatusCode BTManager::setDefaultConnParam(const uint16_t dev_id,
const uint16_t conn_min_interval, const uint16_t conn_max_interval,
const uint16_t conn_latency, const uint16_t supervision_timeout) noexcept {