aboutsummaryrefslogtreecommitdiffstats
path: root/src/direct_bt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2022-04-14 05:22:32 +0200
committerSven Gothel <[email protected]>2022-04-14 05:22:32 +0200
commita86a1f6aae0c5152dfb0695a9bc4e02f3aadb967 (patch)
treea0f9e475a76759c498ebba968a153a591f8b9a25 /src/direct_bt
parentf258c4036a486ccbb22b07ed51783c7cb6d4d52b (diff)
Fixes slave/server legacy LTK issue: Resolve MgmtLongTermKeyInfo::{initiator->role} field's actual role, depending on the adapter's role
BlueZ interprets `role` as follows: - Adapter role slave/responder (GATT server) - 1 = master/initiator (GATT client); 0 = slave/responder (GATT server) - Adapter role master/initiator (GATT client) - 0 = master/initiator (GATT client); 1 = slave/responder (GATT server)
Diffstat (limited to 'src/direct_bt')
-rw-r--r--src/direct_bt/BTDevice.cpp66
-rw-r--r--src/direct_bt/BTManager.cpp31
2 files changed, 36 insertions, 61 deletions
diff --git a/src/direct_bt/BTDevice.cpp b/src/direct_bt/BTDevice.cpp
index 9bf55de5..6359f958 100644
--- a/src/direct_bt/BTDevice.cpp
+++ b/src/direct_bt/BTDevice.cpp
@@ -711,21 +711,9 @@ bool BTDevice::checkPairingKeyDistributionComplete() const noexcept {
{
const SMPKeyType key_mask = pairing_data.use_sc ? _key_mask_sc : _key_mask_legacy;
- // Spec allows remote party to not distribute the keys,
- // hence distribution is complete with local keys!
- // Impact of missing remote keys: Requires new pairing each connection (except local LinkKey)
- if( BTRole::Slave == btRole ) {
- // Remote device is slave (peripheral, responder), we are master (initiator)
- if( ( pairing_data.keys_init_has & key_mask ) == ( pairing_data.keys_init_exp & key_mask ) ) {
- // pairing_data.keys_resp_has == ( pairing_data.keys_resp_exp & key_mask )
- res = true;
- }
- } else {
- // Remote device is master (initiator), we are slave (peripheral, responder)
- if( ( pairing_data.keys_resp_has & key_mask ) == ( pairing_data.keys_resp_exp & key_mask ) ) {
- // pairing_data.keys_init_has == ( pairing_data.keys_init_exp & key_mask )
- res = true;
- }
+ if( ( pairing_data.keys_init_has & key_mask ) == ( pairing_data.keys_init_exp & key_mask ) &&
+ ( pairing_data.keys_resp_has & key_mask ) == ( pairing_data.keys_resp_exp & key_mask ) ) {
+ res = true;
}
}
@@ -983,7 +971,7 @@ bool BTDevice::updatePairingState(std::shared_ptr<BTDevice> sthis, const MgmtEve
// SMP pairing has started, mngr issued new LTK command
const MgmtEvtNewLongTermKey& event = *static_cast<const MgmtEvtNewLongTermKey *>(&evt);
const MgmtLongTermKeyInfo& mgmt_ltk = event.getLongTermKey();
- const SMPLongTermKey smp_ltk = mgmt_ltk.toSMPLongTermKeyInfo();
+ const SMPLongTermKey smp_ltk = mgmt_ltk.toSMPLongTermKeyInfo(!btRole);
if( smp_ltk.isValid() ) {
// Secure Connections (SC) use AES sync key for both, initiator and responder.
if( pairing_data.use_sc || smp_ltk.isResponder() ) {
@@ -1507,39 +1495,21 @@ HCIStatusCode BTDevice::uploadKeys() noexcept {
BTManager & mngr = adapter.getManager();
HCIStatusCode res = HCIStatusCode::SUCCESS;
- if( BTRole::Slave == btRole ) {
- // Remote device is slave (peripheral, responder), we are master (initiator)
- if( ( SMPKeyType::ENC_KEY & pairing_data.keys_init_has ) != SMPKeyType::NONE ) {
- res = mngr.uploadLongTermKey(adapter.dev_id, addressAndType, pairing_data.ltk_init);
- DBG_PRINT("BTDevice::uploadKeys.LTK[Remote slave, master/init]: %s", to_string(res).c_str());
- if( HCIStatusCode::SUCCESS != res ) {
- return res;
- }
- }
-
- if( ( SMPKeyType::ENC_KEY & pairing_data.keys_resp_has ) != SMPKeyType::NONE ) {
- res = mngr.uploadLongTermKey(adapter.dev_id, addressAndType, pairing_data.ltk_resp);
- DBG_PRINT("BTDevice::uploadKeys.LTK[Remote slave, peripheral/resp]: %s", to_string(res).c_str());
- if( HCIStatusCode::SUCCESS != res ) {
- return res;
- }
- }
- } else {
- // Remote device is master (initiator), we are slave (peripheral, responder)
- if( ( SMPKeyType::ENC_KEY & pairing_data.keys_resp_has ) != SMPKeyType::NONE ) {
- res = mngr.uploadLongTermKey(adapter.dev_id, addressAndType, pairing_data.ltk_resp);
- DBG_PRINT("BTDevice::uploadKeys.LTK[Remote master, peripheral/resp]: %s", to_string(res).c_str());
- if( HCIStatusCode::SUCCESS != res ) {
- return res;
- }
+ jau::darray<SMPLongTermKey> ltks;
+ if( ( SMPKeyType::ENC_KEY & pairing_data.keys_init_has ) != SMPKeyType::NONE ) {
+ ltks.push_back(pairing_data.ltk_init);
+ }
+ if( ( SMPKeyType::ENC_KEY & pairing_data.keys_resp_has ) != SMPKeyType::NONE ) {
+ ltks.push_back(pairing_data.ltk_resp);
+ }
+ if( ltks.size() > 0 ) {
+ res = mngr.uploadLongTermKey(!btRole, adapter.dev_id, addressAndType, ltks);
+ if( jau::environment::get().debug ) {
+ const std::string role_s = BTRole::Slave == btRole ? "Remote slave, master/init" : "Remote master, peripheral/resp";
+ DBG_PRINT("BTDevice::uploadKeys.LTK[%s]: %s", role_s.c_str(), to_string(res).c_str());
}
-
- if( ( SMPKeyType::ENC_KEY & pairing_data.keys_init_has ) != SMPKeyType::NONE ) {
- res = mngr.uploadLongTermKey(adapter.dev_id, addressAndType, pairing_data.ltk_init);
- DBG_PRINT("BTDevice::uploadKeys.LTK[Remote master, master/init]: %s", to_string(res).c_str());
- if( HCIStatusCode::SUCCESS != res ) {
- return res;
- }
+ if( HCIStatusCode::SUCCESS != res ) {
+ return res;
}
}
diff --git a/src/direct_bt/BTManager.cpp b/src/direct_bt/BTManager.cpp
index e92b8f38..c45fd7be 100644
--- a/src/direct_bt/BTManager.cpp
+++ b/src/direct_bt/BTManager.cpp
@@ -769,10 +769,10 @@ bool BTManager::isValidLongTermKeyAddressAndType(const EUI48 &address, const BDA
}
}
-HCIStatusCode BTManager::uploadLongTermKey(const uint16_t dev_id, const MgmtLongTermKeyInfo &key) noexcept {
+HCIStatusCode BTManager::uploadLongTermKey(const uint16_t dev_id, const jau::darray<MgmtLongTermKeyInfo> &keys) noexcept {
if constexpr ( USE_LINUX_BT_SECURITY ) {
- const bool is_valid_ltk_addr = isValidLongTermKeyAddressAndType(key.address, key.address_type);
- MgmtLoadLongTermKeyCmd req(dev_id, key);
+ // const bool is_valid_ltk_addr = isValidLongTermKeyAddressAndType(key.address, key.address_type);
+ MgmtLoadLongTermKeyCmd req(dev_id, keys);
HCIStatusCode res;
std::unique_ptr<MgmtEvent> reply = sendWithReply(req);
if( nullptr != reply ) {
@@ -787,11 +787,11 @@ HCIStatusCode BTManager::uploadLongTermKey(const uint16_t dev_id, const MgmtLong
res = HCIStatusCode::TIMEOUT;
}
if( HCIStatusCode::SUCCESS != res ) {
- WARN_PRINT("(dev_id %d): %s (valid_ltk_addr %d), result %s", dev_id,
- req.toString().c_str(), is_valid_ltk_addr, to_string(res).c_str());
+ WARN_PRINT("(dev_id %d): %s, result %s", dev_id,
+ req.toString().c_str(), to_string(res).c_str());
} else {
- DBG_PRINT("BTManager::uploadLongTermKeyInfo(dev_id %d): %s (valid_ltk_addr %d), result %s", dev_id,
- req.toString().c_str(), is_valid_ltk_addr, to_string(res).c_str());
+ DBG_PRINT("BTManager::uploadLongTermKeyInfo(dev_id %d): %s, result %s", dev_id,
+ req.toString().c_str(), to_string(res).c_str());
}
return res;
} else {
@@ -799,14 +799,19 @@ HCIStatusCode BTManager::uploadLongTermKey(const uint16_t dev_id, const MgmtLong
}
}
-HCIStatusCode BTManager::uploadLongTermKey(const uint16_t dev_id, const BDAddressAndType & addressAndType,
- const SMPLongTermKey& ltk) noexcept
+HCIStatusCode BTManager::uploadLongTermKey(const BTRole adapterRole,
+ const uint16_t dev_id, const BDAddressAndType & addressAndType,
+ const jau::darray<SMPLongTermKey>& ltks) noexcept
{
if constexpr ( USE_LINUX_BT_SECURITY ) {
- const MgmtLTKType key_type = to_MgmtLTKType(ltk.properties);
- const MgmtLongTermKeyInfo mgmt_ltk_info { addressAndType.address, addressAndType.type, key_type,
- ltk.isResponder(), ltk.enc_size, ltk.ediv, ltk.rand, ltk.ltk };
- return uploadLongTermKey(dev_id, mgmt_ltk_info);
+ jau::darray<MgmtLongTermKeyInfo> mgmt_keys;
+ for(SMPLongTermKey ltk : ltks) {
+ const MgmtLTKType key_type = to_MgmtLTKType(ltk.properties);
+ mgmt_keys.push_back( { addressAndType.address, addressAndType.type, key_type,
+ MgmtLongTermKeyInfo::to_role( adapterRole, ltk.isResponder() ),
+ ltk.enc_size, ltk.ediv, ltk.rand, ltk.ltk } );
+ }
+ return uploadLongTermKey(dev_id, mgmt_keys);
} else {
return HCIStatusCode::NOT_SUPPORTED;
}