if (gd_acl_enabled && !gd_controller_enabled) {
gd_controller_enabled = true;
}
+ if (gd_l2cap_enabled) {
+ gd_acl_enabled = false;
+ gd_hci_enabled = true;
+ }
if (gd_controller_enabled && !gd_hci_enabled) {
gd_hci_enabled = true;
}
virtual std::unique_ptr<DynamicChannelManager> GetDynamicChannelManager();
static const ModuleFactory Factory;
+ /**
+ * Only for the classic security module to inject functionality to enforce security level for a connection. When
+ * classic security module is stopping, inject nullptr. Note: We expect this only to be called during stack startup.
+ * This is not synchronized.
+ */
+ virtual void InjectSecurityEnforcementInterface(SecurityEnforcementInterface* security_enforcement_interface);
+
+ /**
+ * Get the interface for Security Module to access link function.
+ * Security Module needs to register the callback for ACL link connected and disconnected. When connected, either by
+ * incoming or by outgoing connection request, Security Module receives a LinkSecurityInterface proxy, which can be
+ * used to access some link functionlities.
+ */
+ virtual SecurityInterface* GetSecurityInterface(os::Handler* handler, LinkSecurityInterfaceListener* listener);
protected:
void ListDependencies(ModuleList* list) override;
std::unique_ptr<impl> pimpl_;
friend security::SecurityModule;
- /**
- * Only for the classic security module to inject functionality to enforce security level for a connection. When
- * classic security module is stopping, inject nullptr. Note: We expect this only to be called during stack startup.
- * This is not synchronized.
- */
- virtual void InjectSecurityEnforcementInterface(SecurityEnforcementInterface* security_enforcement_interface);
-
- /**
- * Get the interface for Security Module to access link function.
- * Security Module needs to register the callback for ACL link connected and disconnected. When connected, either by
- * incoming or by outgoing connection request, Security Module receives a LinkSecurityInterface proxy, which can be
- * used to access some link functionlities.
- */
- virtual SecurityInterface* GetSecurityInterface(os::Handler* handler, LinkSecurityInterfaceListener* listener);
DISALLOW_COPY_AND_ASSIGN(L2capClassicModule);
};
LOG_WARN("Unimplemented");
return BTM_SUCCESS;
}
-
-static std::unordered_map<intptr_t,
- bluetooth::common::ContextualOnceCallback<void(bool)>>
- security_enforce_callback_map;
-static intptr_t security_enforce_callback_counter = 0;
-
-static void security_enforce_result_callback(const RawAddress* bd_addr,
- tBT_TRANSPORT trasnport,
- void* p_ref_data,
- tBTM_STATUS result) {
- intptr_t counter = (intptr_t)p_ref_data;
- if (security_enforce_callback_map.count(security_enforce_callback_counter) ==
- 0) {
- LOG(ERROR) << __func__ << "Unknown callback";
- return;
- }
- auto& callback = security_enforce_callback_map[counter];
- std::move(callback).Invoke(result == BTM_SUCCESS);
- security_enforce_callback_map.erase(counter);
-}
-
-class SecurityEnforcementShim
- : public bluetooth::l2cap::classic::SecurityEnforcementInterface {
- public:
- void Enforce(bluetooth::hci::AddressWithType remote,
- bluetooth::l2cap::classic::SecurityPolicy policy,
- ResultCallback result_callback) override {
- uint16_t sec_mask = 0;
- switch (policy) {
- case bluetooth::l2cap::classic::SecurityPolicy::
- _SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK:
- break;
- case bluetooth::l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT:
- sec_mask = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT |
- BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT;
- break;
- case bluetooth::l2cap::classic::SecurityPolicy::BEST:
- case bluetooth::l2cap::classic::SecurityPolicy::
- AUTHENTICATED_ENCRYPTED_TRANSPORT:
- sec_mask = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT |
- BTM_SEC_IN_MITM | BTM_SEC_OUT_AUTHENTICATE |
- BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_MITM;
- break;
- }
- auto bd_addr = bluetooth::ToRawAddress(remote.GetAddress());
- btm_sec_l2cap_access_req_by_requirement(
- bd_addr, sec_mask, true, security_enforce_result_callback,
- (void*)security_enforce_callback_counter);
- security_enforce_callback_counter++;
- }
-};
return Stack::GetInstance()->GetStackManager()->GetInstance<L2cap>();
}
+l2cap::classic::L2capClassicModule* GetL2capClassicModule() {
+ return Stack::GetInstance()
+ ->GetStackManager()
+ ->GetInstance<bluetooth::l2cap::classic::L2capClassicModule>();
+}
+
bluetooth::l2cap::le::L2capLeModule* GetL2capLeModule() {
return Stack::GetInstance()
->GetStackManager()
}
namespace l2cap {
+namespace classic {
+class L2capClassicModule;
+} // namespace classic
namespace le {
class L2capLeModule;
} // namespace le
neighbor::InquiryModule* GetInquiry();
hci::HciLayer* GetHciLayer();
L2cap* GetL2cap();
+l2cap::classic::L2capClassicModule* GetL2capClassicModule();
l2cap::le::L2capLeModule* GetL2capLeModule();
neighbor::NameModule* GetName();
neighbor::PageModule* GetPage();
#define LOG_TAG "bt_shim_l2cap"
#include "main/shim/l2c_api.h"
+#include "gd/l2cap/classic/l2cap_classic_module.h"
#include "gd/l2cap/le/l2cap_le_module.h"
#include "gd/os/log.h"
#include "gd/os/queue.h"
#include "main/shim/l2cap.h"
#include "main/shim/stack.h"
#include "osi/include/allocator.h"
+#include "stack/btm/btm_sec.h"
+#include "stack/include/acl_hci_link_interface.h"
+#include "stack/include/btm_api.h"
static bluetooth::shim::legacy::L2cap shim_l2cap;
+// Helper: L2cap security enforcement shim
+
+std::unordered_map<intptr_t,
+ bluetooth::common::ContextualOnceCallback<void(bool)>>
+ security_enforce_callback_map = {};
+
+class SecurityEnforcementShim
+ : public bluetooth::l2cap::classic::SecurityEnforcementInterface {
+ public:
+ static void security_enforce_result_callback(const RawAddress* bd_addr,
+ tBT_TRANSPORT trasnport,
+ void* p_ref_data,
+ tBTM_STATUS result) {
+ intptr_t counter = (intptr_t)p_ref_data;
+ if (security_enforce_callback_map.count(counter) == 0) {
+ LOG_ERROR("Received unexpected callback");
+ return;
+ }
+
+ auto& callback = security_enforce_callback_map[counter];
+ std::move(callback).Invoke(result == BTM_SUCCESS);
+ security_enforce_callback_map.erase(counter);
+ }
+
+ void Enforce(bluetooth::hci::AddressWithType remote,
+ bluetooth::l2cap::classic::SecurityPolicy policy,
+ ResultCallback result_callback) override {
+ uint16_t sec_mask = 0;
+ switch (policy) {
+ case bluetooth::l2cap::classic::SecurityPolicy::
+ _SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK:
+ result_callback.Invoke(true);
+ return;
+ case bluetooth::l2cap::classic::SecurityPolicy::ENCRYPTED_TRANSPORT:
+ sec_mask = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT |
+ BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT;
+ break;
+ case bluetooth::l2cap::classic::SecurityPolicy::BEST:
+ case bluetooth::l2cap::classic::SecurityPolicy::
+ AUTHENTICATED_ENCRYPTED_TRANSPORT:
+ sec_mask = BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT |
+ BTM_SEC_IN_MITM | BTM_SEC_OUT_AUTHENTICATE |
+ BTM_SEC_OUT_ENCRYPT | BTM_SEC_OUT_MITM;
+ break;
+ }
+ auto bd_addr = bluetooth::ToRawAddress(remote.GetAddress());
+ security_enforce_callback_map[security_enforce_callback_counter_] =
+ std::move(result_callback);
+ btm_sec_l2cap_access_req_by_requirement(
+ bd_addr, sec_mask, true, security_enforce_result_callback,
+ (void*)security_enforce_callback_counter_);
+ security_enforce_callback_counter_++;
+ }
+
+ intptr_t security_enforce_callback_counter_ = 100;
+} security_enforcement_shim_;
+
+class SecurityListenerShim
+ : public bluetooth::l2cap::classic::LinkSecurityInterfaceListener {
+ public:
+ void OnLinkConnected(
+ std::unique_ptr<bluetooth::l2cap::classic::LinkSecurityInterface>
+ interface) override {
+ auto bda = bluetooth::ToRawAddress(interface->GetRemoteAddress());
+
+ uint16_t handle = interface->GetAclHandle();
+ address_to_handle_[bda] = handle;
+ btm_acl_connected(bda, handle, HCI_SUCCESS, 0);
+ address_to_interface_[bda] = std::move(interface);
+ }
+
+ void OnAuthenticationComplete(bluetooth::hci::Address remote) override {
+ auto bda = bluetooth::ToRawAddress(remote);
+ uint16_t handle = address_to_handle_[bda];
+ btm_sec_auth_complete(handle, HCI_SUCCESS);
+ }
+
+ void OnLinkDisconnected(bluetooth::hci::Address remote) override {
+ auto bda = bluetooth::ToRawAddress(remote);
+ uint16_t handle = address_to_handle_[bda];
+ btm_acl_disconnected(HCI_SUCCESS, handle, HCI_ERR_PEER_USER);
+ address_to_handle_.erase(bda);
+ address_to_interface_.erase(bda);
+ }
+
+ void OnEncryptionChange(bluetooth::hci::Address remote,
+ bool encrypted) override {
+ auto bda = bluetooth::ToRawAddress(remote);
+ uint16_t handle = address_to_handle_[bda];
+ btm_sec_encrypt_change(handle, HCI_SUCCESS, encrypted);
+ }
+
+ void OnReadRemoteVersionInformation(bluetooth::hci::Address remote,
+ uint8_t lmp_version,
+ uint16_t manufacturer_name,
+ uint16_t sub_version) override {
+ auto bda = bluetooth::ToRawAddress(remote);
+ uint16_t handle = address_to_handle_[bda];
+
+ btm_read_remote_version_complete(HCI_SUCCESS, handle, lmp_version,
+ manufacturer_name, sub_version);
+ }
+
+ void OnReadRemoteExtendedFeatures(bluetooth::hci::Address remote,
+ uint8_t page_number,
+ uint8_t max_page_number,
+ uint64_t features) override {
+ auto bda = bluetooth::ToRawAddress(remote);
+ uint16_t handle = address_to_handle_[bda];
+ uint8_t* features_array = (uint8_t*)&features;
+ if (page_number == 0) {
+ btm_read_remote_features_complete(handle, features_array);
+ } else {
+ btm_read_remote_ext_features_complete(handle, page_number,
+ max_page_number, features_array);
+ }
+ }
+
+ void UpdateLinkHoldForSecurity(RawAddress remote, bool is_bonding) {
+ if (address_to_interface_.count(remote) == 0) {
+ return;
+ }
+ if (is_bonding) {
+ address_to_interface_[remote]->Hold();
+ } else {
+ address_to_interface_[remote]->Release();
+ }
+ }
+
+ std::unordered_map<RawAddress, uint16_t> address_to_handle_;
+ std::unordered_map<
+ RawAddress,
+ std::unique_ptr<bluetooth::l2cap::classic::LinkSecurityInterface>>
+ address_to_interface_;
+} security_listener_shim_;
+
+bluetooth::l2cap::classic::SecurityInterface* security_interface_ = nullptr;
+
+void bluetooth::shim::L2CA_UseLegacySecurityModule() {
+ LOG_INFO("GD L2cap is using legacy security module");
+ bluetooth::shim::GetL2capClassicModule()->InjectSecurityEnforcementInterface(
+ &security_enforcement_shim_);
+ security_interface_ =
+ bluetooth::shim::GetL2capClassicModule()->GetSecurityInterface(
+ bluetooth::shim::GetGdShimHandler(), &security_listener_shim_);
+}
+
/**
* Classic Service Registration APIs
*/
return true;
}
+void bluetooth::shim::L2CA_ConnectForSecurity(const RawAddress& bd_addr) {
+ security_interface_->InitiateConnectionForSecurity(
+ bluetooth::ToGdAddress(bd_addr));
+}
+
+void bluetooth::shim::L2CA_SetBondingState(const RawAddress& bd_addr,
+ bool is_bonding) {
+ security_listener_shim_.UpdateLinkHoldForSecurity(bd_addr, is_bonding);
+}
+
// LE COC Shim Helper
uint16_t cid_token_counter_ = 1;
*/
bool L2CA_IsLinkEstablished(const RawAddress& bd_addr, tBT_TRANSPORT transport);
+void L2CA_ConnectForSecurity(const RawAddress& bd_addr);
+
+// Set bonding state to acquire/release link refcount
+void L2CA_SetBondingState(const RawAddress& p_bd_addr, bool is_bonding);
+
+// Indicated by shim stack manager that GD L2cap is enabled but Security is not
+void L2CA_UseLegacySecurityModule();
+
} // namespace shim
} // namespace bluetooth
}
bool bluetooth::shim::is_gd_l2cap_enabled() {
- // TODO(hsz): Use L2cap flag
return bluetooth::common::InitFlags::GdL2capEnabled();
}
#include "main/shim/acl_legacy_interface.h"
#include "main/shim/hci_layer.h"
+#include "main/shim/helpers.h"
+#include "main/shim/l2c_api.h"
#include "main/shim/le_advertising_manager.h"
#include "main/shim/shim.h"
#include "main/shim/stack.h"
if (common::InitFlags::GdAclEnabled()) {
modules.add<hci::AclManager>();
}
+ if (common::InitFlags::GdL2capEnabled()) {
+ modules.add<l2cap::classic::L2capClassicModule>();
+ modules.add<l2cap::le::L2capLeModule>();
+ modules.add<shim::L2cap>();
+ }
if (common::InitFlags::GdSecurityEnabled()) {
modules.add<security::SecurityModule>();
}
if (common::InitFlags::GdCoreEnabled()) {
modules.add<att::AttModule>();
modules.add<hci::LeScanningManager>();
- modules.add<l2cap::classic::L2capClassicModule>();
- modules.add<l2cap::le::L2capLeModule>();
modules.add<neighbor::ConnectabilityModule>();
modules.add<neighbor::DiscoverabilityModule>();
modules.add<neighbor::InquiryModule>();
modules.add<neighbor::PageModule>();
modules.add<neighbor::ScanModule>();
modules.add<storage::StorageModule>();
- modules.add<shim::L2cap>();
}
Start(&modules);
+ is_running_ = true;
// Make sure the leaf modules are started
ASSERT(stack_manager_.GetInstance<storage::StorageModule>() != nullptr);
ASSERT(stack_manager_.GetInstance<shim::Dumpsys>() != nullptr);
btm_ = new Btm(stack_handler_,
stack_manager_.GetInstance<neighbor::InquiryModule>());
}
- is_running_ = true;
if (common::InitFlags::GdAclEnabled()) {
if (!common::InitFlags::GdCoreEnabled()) {
acl_ = new legacy::Acl(stack_handler_, legacy::GetAclInterface());
if (common::InitFlags::GdAdvertisingEnabled()) {
bluetooth::shim::init_advertising_manager();
}
+ if (common::InitFlags::GdL2capEnabled() &&
+ !common::InitFlags::GdCoreEnabled()) {
+ L2CA_UseLegacySecurityModule();
+ }
}
void Stack::Start(ModuleList* modules) {