aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/direct_bt/BTAdapter.hpp4
-rw-r--r--api/direct_bt/BTManager.hpp2
-rw-r--r--api/direct_bt/MgmtTypes.hpp28
-rw-r--r--examples/dbt_scanner10.cpp7
-rw-r--r--src/direct_bt/BTAdapter.cpp65
-rw-r--r--src/direct_bt/BTManager.cpp8
6 files changed, 113 insertions, 1 deletions
diff --git a/api/direct_bt/BTAdapter.hpp b/api/direct_bt/BTAdapter.hpp
index 4370d791..308f2457 100644
--- a/api/direct_bt/BTAdapter.hpp
+++ b/api/direct_bt/BTAdapter.hpp
@@ -349,6 +349,7 @@ namespace direct_bt {
*/
BDAddressAndType visibleAddressAndType;
HCILEOwnAddressType visibleMACType;
+ MgmtIdentityResolvingKeyInfo privacyIRK;
public:
typedef jau::nsize_t size_type;
@@ -527,6 +528,7 @@ namespace direct_bt {
void mgmtEvPairDeviceCompleteMgmt(const MgmtEvent& e) noexcept;
void mgmtEvNewLongTermKeyMgmt(const MgmtEvent& e) noexcept;
void mgmtEvNewLinkKeyMgmt(const MgmtEvent& e) noexcept;
+ void mgmtEvNewIdentityResolvingKeyMgmt(const MgmtEvent& e) noexcept;
void mgmtEvHCIAnyHCI(const MgmtEvent& e) noexcept;
void mgmtEvDeviceDiscoveringHCI(const MgmtEvent& e) noexcept;
@@ -745,6 +747,8 @@ namespace direct_bt {
*/
bool setPowered(const bool power_on) noexcept;
+ HCIStatusCode setPrivacy(const bool enable) noexcept;
+
/**
* Returns whether Secure Connections (SC) is enabled.
* @see setSecureConnections()
diff --git a/api/direct_bt/BTManager.hpp b/api/direct_bt/BTManager.hpp
index 2bbcc55e..3a80621b 100644
--- a/api/direct_bt/BTManager.hpp
+++ b/api/direct_bt/BTManager.hpp
@@ -420,6 +420,8 @@ namespace direct_bt {
HCIStatusCode initializeAdapter(AdapterInfo& adapterInfo, const uint16_t dev_id,
const BTMode btMode, const bool powerOn) noexcept;
+ HCIStatusCode setPrivacy(const uint16_t dev_id, const uint8_t privacy, const jau::uint128_t& irk, AdapterSetting& current_settings) noexcept;
+
/**
* Read default connection parameter for given adapter to the kernel.
*
diff --git a/api/direct_bt/MgmtTypes.hpp b/api/direct_bt/MgmtTypes.hpp
index 444e3035..9329edd3 100644
--- a/api/direct_bt/MgmtTypes.hpp
+++ b/api/direct_bt/MgmtTypes.hpp
@@ -826,6 +826,34 @@ namespace direct_bt {
};
/**
+ * uint8_t privacy 0x00 disabled, 0x01 always on (discoverable + pairing), 0x02 limited (not when discoverable, bondable)
+ * jau::uint128_t irk Identity Resolving Key
+ */
+ class MgmtSetPrivacyCmd : public MgmtCommand
+ {
+ protected:
+ std::string valueString() const noexcept override {
+ const jau::uint128_t& irk = getIdentityResolvingKey();
+ return "param[size "+std::to_string(getParamSize())+", data[privacy "+std::to_string(getPrivacy())+
+ ", irk "+jau::bytesHexString(irk.data, 0, sizeof(irk), true /* lsbFirst */)+"]]";
+ }
+
+ public:
+ MgmtSetPrivacyCmd(const uint16_t dev_id, const uint8_t privacy, const jau::uint128_t& irk)
+ : MgmtCommand(Opcode::SET_PRIVACY, dev_id, 1 + sizeof(irk))
+ {
+ pdu.put_uint8_nc(MGMT_HEADER_SIZE, privacy);
+ memcpy(pdu.get_wptr_nc(MGMT_HEADER_SIZE+1), &irk, sizeof(irk));
+ }
+
+ uint8_t getPrivacy() const noexcept { return pdu.get_uint8_nc(MGMT_HEADER_SIZE); }
+
+ const jau::uint128_t& getIdentityResolvingKey() const {
+ return *reinterpret_cast<const jau::uint128_t *>( pdu.get_ptr_nc(MGMT_HEADER_SIZE + 1) );
+ }
+ };
+
+ /**
* mgmt_addr_info { EUI48, uint8_t type },
*/
class MgmtGetConnectionInfoCmd : public MgmtCmdAdressInfoMeta
diff --git a/examples/dbt_scanner10.cpp b/examples/dbt_scanner10.cpp
index bceb21ef..15c4ddd0 100644
--- a/examples/dbt_scanner10.cpp
+++ b/examples/dbt_scanner10.cpp
@@ -113,6 +113,7 @@ static uint64_t timestamp_t0;
static EUI48 useAdapter = EUI48::ALL_DEVICE;
static BTMode btMode = BTMode::DUAL;
+static bool use_privacy = false;
static DiscoveryPolicy discoveryPolicy = DiscoveryPolicy::PAUSE_CONNECTED_UNTIL_READY; // default value
static bool le_scan_active = true; // default value
@@ -637,6 +638,7 @@ static bool initAdapter(std::shared_ptr<BTAdapter>& adapter) {
to_string(status).c_str(), adapter->toString().c_str());
return false;
}
+ adapter->setPrivacy(use_privacy);
}
if( !adapter->setPowered( true ) ) {
fprintf_td(stderr, "initAdapter: Adapter power-on failed:: %s\n", adapter->toString().c_str());
@@ -768,6 +770,8 @@ int main(int argc, char *argv[])
btMode = to_BTMode(argv[++i]);
} else if( !strcmp("-adapter", argv[i]) && argc > (i+1) ) {
useAdapter = EUI48( std::string(argv[++i]) );
+ } else if( !strcmp("-privacy", argv[i]) ) {
+ use_privacy = true;
} else if( !strcmp("-dev", argv[i]) && argc > (i+1) ) {
std::string addrOrNameSub = std::string(argv[++i]);
BTDeviceRegistry::addToWaitForDevices( addrOrNameSub );
@@ -819,6 +823,7 @@ int main(int argc, char *argv[])
"[-scanPassive] "
"[-resetEachCon connectionCount] "
"[-adapter <adapter_address>] "
+ "[-privacy] "
"(-dev <device_[address|name]_sub>)* "
"(-seclevel <device_[address|name]_sub> <int_sec_level>)* "
"(-iocap <device_[address|name]_sub> <int_iocap>)* "
@@ -840,7 +845,7 @@ int main(int argc, char *argv[])
fprintf_td(stderr, "REMOVE_DEVICE %d\n", REMOVE_DEVICE);
fprintf_td(stderr, "SHOW_UPDATE_EVENTS %d\n", SHOW_UPDATE_EVENTS);
fprintf_td(stderr, "QUIET %d\n", QUIET);
- fprintf_td(stderr, "adapter %s\n", useAdapter.toString().c_str());
+ fprintf_td(stderr, "adapter %s, privacy %d\n", useAdapter.toString().c_str(), use_privacy);
fprintf_td(stderr, "btmode %s\n", to_string(btMode).c_str());
fprintf_td(stderr, "discoveryPolicy %s\n", to_string(discoveryPolicy).c_str());
fprintf_td(stderr, "scanActive %s\n", to_string(le_scan_active).c_str());
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 {