OSDN Git Service

Introduce L2cap security shim
authorHansong Zhang <hsz@google.com>
Wed, 28 Oct 2020 23:46:15 +0000 (16:46 -0700)
committerHansong Zhang <hsz@google.com>
Fri, 6 Nov 2020 19:07:58 +0000 (11:07 -0800)
L2cap security shim lets GD L2cap wants to enforce security requirements
on legacy security module.

Implementing the GD security interface.

Tag: #gd-refactor
Bug: 141555841
Test: cert/run --host
Test: Pair and connect with a headset
Change-Id: I60cd99566011f3eb93ecd6b32b1f428e8d69733d

gd/common/init_flags.cc
gd/l2cap/classic/l2cap_classic_module.h
main/shim/btm_api.cc
main/shim/entry.cc
main/shim/entry.h
main/shim/l2c_api.cc
main/shim/l2c_api.h
main/shim/shim.cc
main/shim/stack.cc

index 7a8f0ed..e62bddf 100644 (file)
@@ -98,6 +98,10 @@ void InitFlags::Load(const char** flags) {
   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;
   }
index f154a10..1e6a100 100644 (file)
@@ -48,6 +48,20 @@ class L2capClassicModule : public bluetooth::Module {
   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;
@@ -65,20 +79,6 @@ class L2capClassicModule : public bluetooth::Module {
   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);
 };
index b8c90c1..740f63c 100644 (file)
@@ -1343,54 +1343,3 @@ tBTM_STATUS bluetooth::shim::BTM_SetDeviceClass(DEV_CLASS dev_class) {
   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++;
-  }
-};
index ff9aefa..a0e4e04 100644 (file)
@@ -81,6 +81,12 @@ L2cap* GetL2cap() {
   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()
index 2508aae..2380426 100644 (file)
@@ -52,6 +52,9 @@ class LeScanningManager;
 }
 
 namespace l2cap {
+namespace classic {
+class L2capClassicModule;
+}  // namespace classic
 namespace le {
 class L2capLeModule;
 }  // namespace le
@@ -77,6 +80,7 @@ Dumpsys* GetDumpsys();
 neighbor::InquiryModule* GetInquiry();
 hci::HciLayer* GetHciLayer();
 L2cap* GetL2cap();
+l2cap::classic::L2capClassicModule* GetL2capClassicModule();
 l2cap::le::L2capLeModule* GetL2capLeModule();
 neighbor::NameModule* GetName();
 neighbor::PageModule* GetPage();
index 166e78c..638cd7d 100644 (file)
@@ -17,6 +17,7 @@
 #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
  */
@@ -390,6 +541,16 @@ bool bluetooth::shim::L2CA_IsLinkEstablished(const RawAddress& bd_addr,
   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;
index 75480ba..6971e29 100644 (file)
@@ -507,5 +507,13 @@ void L2CA_AdjustConnectionIntervals(uint16_t* min_interval,
  */
 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
index bb591bf..ea28049 100644 (file)
@@ -77,7 +77,6 @@ bool bluetooth::shim::is_gd_controller_enabled() {
 }
 
 bool bluetooth::shim::is_gd_l2cap_enabled() {
-  // TODO(hsz): Use L2cap flag
   return bluetooth::common::InitFlags::GdL2capEnabled();
 }
 
index 65dc31d..3a7e15e 100644 (file)
@@ -41,6 +41,8 @@
 
 #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"
@@ -82,6 +84,11 @@ void Stack::StartEverything() {
   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>();
   }
@@ -91,8 +98,6 @@ void Stack::StartEverything() {
   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>();
@@ -101,9 +106,9 @@ void Stack::StartEverything() {
     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);
@@ -112,7 +117,6 @@ void Stack::StartEverything() {
     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());
@@ -125,6 +129,10 @@ void Stack::StartEverything() {
   if (common::InitFlags::GdAdvertisingEnabled()) {
     bluetooth::shim::init_advertising_manager();
   }
+  if (common::InitFlags::GdL2capEnabled() &&
+      !common::InitFlags::GdCoreEnabled()) {
+    L2CA_UseLegacySecurityModule();
+  }
 }
 
 void Stack::Start(ModuleList* modules) {