diff options
author | Sven Gothel <[email protected]> | 2023-10-22 05:47:20 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2023-10-22 05:47:20 +0200 |
commit | 116ce8e5a4672b963a4b2bbb2054158a77f8417b (patch) | |
tree | 7f388682118553ba2b7e344b25d6a03cb63b0205 /src | |
parent | 701ed7e6dbebbc2118726f203ae576df73ea5e2d (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.cpp | 65 | ||||
-rw-r--r-- | src/direct_bt/BTManager.cpp | 8 |
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 { |