Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 403aafd2 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Introduce LE COC security enforcement shim

Tag: #gd-refactor
Bug: 141555841
Test: cert/run --host
Test: Pair and connect with a headset
Change-Id: Iad2d1e71582886c05a4c7df39cc85735cb3f8abf
parent fd31d9cc
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@

namespace bluetooth {

namespace shim {
void L2CA_UseLegacySecurityModule();
}

namespace security {
class SecurityModule;
}
@@ -62,6 +66,8 @@ class L2capLeModule : public bluetooth::Module {
  std::unique_ptr<impl> pimpl_;

  friend security::SecurityModule;
  friend void bluetooth::shim::L2CA_UseLegacySecurityModule();

  /**
   * Only for the LE security module to inject functionality to enforce security level for a connection. When LE
   * security module is stopping, inject nullptr. Note: We expect this only to be called during stack startup. This is
+89 −8
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ std::unordered_map<intptr_t,
                   bluetooth::common::ContextualOnceCallback<void(bool)>>
    security_enforce_callback_map = {};

class SecurityEnforcementShim
class ClassicSecurityEnforcementShim
    : public bluetooth::l2cap::classic::SecurityEnforcementInterface {
 public:
  static void security_enforce_result_callback(const RawAddress* bd_addr,
@@ -178,6 +178,14 @@ class SecurityListenerShim
    }
  }

  bool IsRoleCentral(RawAddress remote) {
    if (address_to_interface_.count(remote) == 0) {
      return false;
    }
    return address_to_interface_[remote]->GetRole() ==
           bluetooth::hci::Role::CENTRAL;
  }

  std::unordered_map<RawAddress, uint16_t> address_to_handle_;
  std::unordered_map<
      RawAddress,
@@ -187,6 +195,60 @@ class SecurityListenerShim

bluetooth::l2cap::classic::SecurityInterface* security_interface_ = nullptr;

std::unordered_map<intptr_t,
                   bluetooth::common::ContextualOnceCallback<void(bool)>>
    le_security_enforce_callback_map = {};

class LeSecurityEnforcementShim
    : public bluetooth::l2cap::le::SecurityEnforcementInterface {
 public:
  static void le_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 (le_security_enforce_callback_map.count(counter) == 0) {
      LOG_ERROR("Received unexpected callback");
      return;
    }

    auto& callback = le_security_enforce_callback_map[counter];
    std::move(callback).Invoke(result == BTM_SUCCESS);
    le_security_enforce_callback_map.erase(counter);
  }

  void Enforce(bluetooth::hci::AddressWithType remote,
               bluetooth::l2cap::le::SecurityPolicy policy,
               ResultCallback result_callback) override {
    tBTM_BLE_SEC_ACT sec_act = 0;
    switch (policy) {
      case bluetooth::l2cap::le::SecurityPolicy::
          NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK:
        result_callback.Invoke(true);
        return;
      case bluetooth::l2cap::le::SecurityPolicy::ENCRYPTED_TRANSPORT:
        sec_act = BTM_BLE_SEC_ENCRYPT;
        break;
      case bluetooth::l2cap::le::SecurityPolicy::BEST:
      case bluetooth::l2cap::le::SecurityPolicy::
          AUTHENTICATED_ENCRYPTED_TRANSPORT:
        sec_act = BTM_BLE_SEC_ENCRYPT_MITM;
        break;
      default:
        result_callback.Invoke(false);
    }
    auto bd_addr = bluetooth::ToRawAddress(remote.GetAddress());
    le_security_enforce_callback_map[security_enforce_callback_counter_] =
        std::move(result_callback);
    BTM_SetEncryption(bd_addr, BT_TRANSPORT_LE,
                      le_security_enforce_result_callback,
                      (void*)security_enforce_callback_counter_, sec_act);
    security_enforce_callback_counter_++;
  }

  intptr_t security_enforce_callback_counter_ = 100;
} le_security_enforcement_shim_;

bool bluetooth::shim::L2CA_ReadRemoteVersion(const RawAddress& addr,
                                             uint8_t* lmp_version,
                                             uint16_t* manufacturer,
@@ -208,6 +270,9 @@ void bluetooth::shim::L2CA_UseLegacySecurityModule() {
  security_interface_ =
      bluetooth::shim::GetL2capClassicModule()->GetSecurityInterface(
          bluetooth::shim::GetGdShimHandler(), &security_listener_shim_);

  bluetooth::shim::GetL2capLeModule()->InjectSecurityEnforcementInterface(
      &le_security_enforcement_shim_);
}

/**
@@ -351,6 +416,7 @@ using bluetooth::l2cap::le::FixedChannelManager;
using bluetooth::l2cap::le::FixedChannelService;

static constexpr uint16_t kAttCid = 4;
static constexpr uint16_t kSmpCid = 6;

struct LeFixedChannelHelper {
  LeFixedChannelHelper(uint16_t cid) : cid_(cid) {}
@@ -444,9 +510,11 @@ struct LeFixedChannelHelper {
};

static LeFixedChannelHelper att_helper{4};
static LeFixedChannelHelper smp_helper{6};
static std::unordered_map<uint16_t, LeFixedChannelHelper&>
    le_fixed_channel_helper_{
        {4, att_helper},
        {6, smp_helper},
    };

/**
@@ -455,7 +523,7 @@ static std::unordered_map<uint16_t, LeFixedChannelHelper&>
 */
bool bluetooth::shim::L2CA_RegisterFixedChannel(uint16_t cid,
                                                tL2CAP_FIXED_CHNL_REG* p_freg) {
  if (cid != kAttCid) {
  if (cid != kAttCid && cid != kSmpCid) {
    LOG(ERROR) << "Invalid cid: " << cid;
    return false;
  }
@@ -479,7 +547,7 @@ bool bluetooth::shim::L2CA_RegisterFixedChannel(uint16_t cid,

bool bluetooth::shim::L2CA_ConnectFixedChnl(uint16_t cid,
                                            const RawAddress& rem_bda) {
  if (cid != kAttCid) {
  if (cid != kAttCid && cid != kSmpCid) {
    LOG(ERROR) << "Invalid cid " << cid;
    return false;
  }
@@ -504,7 +572,7 @@ bool bluetooth::shim::L2CA_ConnectFixedChnl(uint16_t cid,
uint16_t bluetooth::shim::L2CA_SendFixedChnlData(uint16_t cid,
                                                 const RawAddress& rem_bda,
                                                 BT_HDR* p_buf) {
  if (cid != kAttCid) {
  if (cid != kAttCid && cid != kSmpCid) {
    LOG(ERROR) << "Invalid cid " << cid;
    return false;
  }
@@ -518,7 +586,7 @@ uint16_t bluetooth::shim::L2CA_SendFixedChnlData(uint16_t cid,

bool bluetooth::shim::L2CA_RemoveFixedChnl(uint16_t cid,
                                           const RawAddress& rem_bda) {
  if (cid != kAttCid) {
  if (cid != kAttCid && cid != kSmpCid) {
    LOG(ERROR) << "Invalid cid " << cid;
    return false;
  }
@@ -670,6 +738,7 @@ struct LeDynamicChannelHelper {
      return;
    }
    channels_[device]->Close();
    disconnected_by_us_[device] = true;
  }

  void Unregister() {
@@ -682,18 +751,27 @@ struct LeDynamicChannelHelper {
    }
  }

  void on_unregistered() {}
  void on_unregistered() {
    for (const auto& device : channels_) {
      device.second->Close();
    }
  }

  void on_channel_close(bluetooth::hci::AddressWithType device,
                        bluetooth::hci::ErrorCode error_code) {
    channel_enqueue_buffer_[device] = nullptr;
    channels_[device]->GetQueueUpEnd()->UnregisterDequeue();
    channels_[device] = nullptr;
    channels_.erase(device);
    auto address = bluetooth::ToRawAddress(device.GetAddress());
    auto cid_token = find_cid_token_by_psm_address(psm_, address);
    (appl_info_.pL2CA_DisconnectInd_Cb)(cid_token, false);
    remove_cid_token_entry(cid_token);
    initiated_by_us_.erase(device);

    if (channel_service_ == nullptr && channels_.empty()) {
      // Try again
      bluetooth::shim::L2CA_DeregisterLECoc(psm_);
    }
  }

  void on_channel_open(std::unique_ptr<DynamicChannel> channel) {
@@ -773,6 +851,7 @@ struct LeDynamicChannelHelper {
      channel_enqueue_buffer_;
  std::unordered_map<AddressWithType, uint16_t> cid_map_;
  std::unordered_map<AddressWithType, bool> initiated_by_us_;
  std::unordered_map<AddressWithType, bool> disconnected_by_us_;
};

std::unordered_map<uint16_t, std::unique_ptr<LeDynamicChannelHelper>>
@@ -800,8 +879,10 @@ void bluetooth::shim::L2CA_DeregisterLECoc(uint16_t psm) {
    return;
  }
  le_dynamic_channel_helper_map_[psm]->Unregister();
  if (le_dynamic_channel_helper_map_[psm]->channels_.empty()) {
    le_dynamic_channel_helper_map_.erase(psm);
  }
}

uint16_t bluetooth::shim::L2CA_ConnectLECocReq(uint16_t psm,
                                               const RawAddress& p_bd_addr,