diff options
author | Sven Gothel <[email protected]> | 2022-04-14 05:22:32 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-04-14 05:22:32 +0200 |
commit | a86a1f6aae0c5152dfb0695a9bc4e02f3aadb967 (patch) | |
tree | a0f9e475a76759c498ebba968a153a591f8b9a25 /src/direct_bt | |
parent | f258c4036a486ccbb22b07ed51783c7cb6d4d52b (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.cpp | 66 | ||||
-rw-r--r-- | src/direct_bt/BTManager.cpp | 31 |
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; } |