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

Commit 07c40998 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ibffbfeb8,If67b829b,I783c83ed

* changes:
  csip: Don't keep bond with invalid CSIS devices
  smp: Add SIRK verification callback
  gatt: Extend gatt attr with reading of SIRK characteristic
parents a24c9114 102b7e22
Loading
Loading
Loading
Loading
+142 −5
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@
#include "stack/btm/btm_dev.h"
#include "stack/btm/btm_sec.h"
#include "stack/crypto_toolbox/crypto_toolbox.h"
#include "stack/gatt/gatt_int.h"

using base::Closure;
using bluetooth::Uuid;
@@ -131,6 +132,16 @@ class CsisClientImpl : public CsisClient {
            initCb),
        true);

    BTA_DmSirkSecCbRegister([](tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) {
      if (event != BTA_DM_SIRK_VERIFICATION_REQ_EVT) {
        LOG_ERROR("Invalid event received by CSIP: %d",
                  static_cast<int>(event));
        return;
      }

      instance->VerifySetMember(p_data->ble_req.bd_addr);
    });

    DLOG(INFO) << __func__ << " Background scan enabled";
    CsisObserverSetBackground(true);
  }
@@ -706,7 +717,13 @@ class CsisClientImpl : public CsisClient {
             << static_cast<int>(g->GetTargetLockState()) << "\n"
             << "    devices: \n";
      for (auto& device : devices_) {
        if (!g->IsDeviceInTheGroup(device)) continue;
        if (!g->IsDeviceInTheGroup(device)) {
          if (device->GetExpectedGroupIdMember() == g->GetGroupId()) {
            stream << "        == candidate addr: "
                   << ADDRESS_TO_LOGGABLE_STR(device->addr) << "\n";
          }
          continue;
        }

        stream << "        == addr: "
               << ADDRESS_TO_LOGGABLE_STR(device->addr) << " ==\n"
@@ -1224,6 +1241,25 @@ class CsisClientImpl : public CsisClient {
    return std::move(devices);
  }

  void CacheAndAdvertiseExpectedMember(const RawAddress& address,
                                       int group_id) {
    auto device = FindDeviceByAddress(address);
    if (device == nullptr) {
      device = std::make_shared<CsisDevice>(address, false);
      devices_.push_back(device);
    }

    /*
     * Expected group ID will be checked while reading SIRK if this device
     * truly is member of group.
     */
    device.get()->SetExpectedGroupIdMember(group_id);
    devices_.push_back(device);

    callbacks_->OnSetMemberAvailable(address,
                                     device.get()->GetExpectedGroupIdMember());
  }

  void OnActiveScanResult(const tBTA_DM_INQ_RES* result) {
    auto csis_device = FindDeviceByAddress(result->bd_addr);
    if (csis_device) {
@@ -1256,7 +1292,8 @@ class CsisClientImpl : public CsisClient {
    if (discovered_group_rsi != all_rsi.cend()) {
      DLOG(INFO) << "Found set member "
                 << ADDRESS_TO_LOGGABLE_STR(result->bd_addr);
      callbacks_->OnSetMemberAvailable(result->bd_addr,

      CacheAndAdvertiseExpectedMember(result->bd_addr,
                                      csis_group->GetGroupId());

      /* Switch back to the opportunistic observer mode.
@@ -1376,8 +1413,8 @@ class CsisClientImpl : public CsisClient {
            break;
          }

          callbacks_->OnSetMemberAvailable(result->bd_addr,
                                           group->GetGroupId());
          CacheAndAdvertiseExpectedMember(result->bd_addr, group->GetGroupId());

          break;
        }
      }
@@ -1524,6 +1561,24 @@ class CsisClientImpl : public CsisClient {
               << loghex(csis_group->GetDesiredSize())
               << ", actual group Size: "
               << loghex(csis_group->GetCurrentSize());
    if (csis_group->GetDesiredSize() == csis_group->GetCurrentSize()) {
      auto iter = devices_.cbegin();

      /*
       * Remove devices which are expected members but are not connected and
       * group is already completed. Those devices are cached ivalid devices
       * kept on list to not trigger "new device" found every time advertising
       * event is received.
       */
      while (iter != devices_.cend()) {
        if (((*iter)->GetExpectedGroupIdMember() == csis_group->GetGroupId()) &&
            !(*iter)->IsConnected()) {
          iter = devices_.erase(iter);
        } else {
          ++iter;
        }
      }
    }
  }

  void DeregisterNotifications(std::shared_ptr<CsisDevice> device) {
@@ -2049,6 +2104,87 @@ class CsisClientImpl : public CsisClient {
    }
  }

  void ReadSirkValue(tGATT_STATUS status, const RawAddress& address,
                     uint8_t sirk_type, Octet16& received_sirk) {
    if (status != GATT_SUCCESS) {
      LOG_INFO("Invalid member, can't read SIRK (status: %02x)", status);
      BTA_DmSirkConfirmDeviceReply(address, false);
      return;
    }

    auto device = FindDeviceByAddress(address);
    if (device == nullptr) {
      LOG_ERROR("Invalid SIRK value read for unknown device");
      BTA_DmSirkConfirmDeviceReply(address, false);
      return;
    }

    LOG_DEBUG("%s, status: 0x%02x", ADDRESS_TO_LOGGABLE_CSTR(address), status);

    /* Verify if sirk is not all zeros */
    Octet16 zero{};
    if (memcmp(zero.data(), received_sirk.data(), 16) == 0) {
      LOG_ERROR("Received invalid zero SIRK address: %s ",
                ADDRESS_TO_LOGGABLE_CSTR(address));
      BTA_DmSirkConfirmDeviceReply(address, false);
      return;
    }

    if (sirk_type == bluetooth::csis::kCsisSirkTypeEncrypted) {
      /* Decrypt encrypted SIRK */
      Octet16 sirk;
      sdf(device->addr, received_sirk, sirk);
      received_sirk = sirk;
    }

    /* SIRK is ready. Add device to the group */

    /* Now having SIRK we can decide if the device belongs to some group we
     * know or this is a new group
     */
    auto csis_group = FindCsisGroup(device->GetExpectedGroupIdMember());
    if (!csis_group) {
      LOG_ERROR("Expected group with ID: %d, isn't cached",
                device->GetExpectedGroupIdMember());
      return;
    }

    /* Device will be added to group when upper layer decides */
    RemoveDevice(device->addr);

    if (csis_group->IsSirkBelongsToGroup(received_sirk)) {
      LOG_INFO("Device %s, verified successfully by SIRK",
               ADDRESS_TO_LOGGABLE_CSTR(address));
      BTA_DmSirkConfirmDeviceReply(address, true);
    } else {
      /*
       * Joining member must join already existing group otherwise it means
       * that its SIRK is different. Device connection was triggered by RSI
       * match for group.
       */
      LOG_ERROR("Joining device %s, does not match any existig group",
                ADDRESS_TO_LOGGABLE_CSTR(address));
      BTA_DmSirkConfirmDeviceReply(address, false);
    }
  }

  void VerifySetMember(const RawAddress& address) {
    auto device = FindDeviceByAddress(address);

    LOG_INFO("Device: %s", ADDRESS_TO_LOGGABLE_CSTR(address));

    /* It's ok for device to not be a CSIS device at all */
    if (!device) {
      LOG_INFO("Valid - new member");
      BTA_DmSirkConfirmDeviceReply(address, true);
      return;
    }

    gatt_cl_read_sirk_req(address,
                          base::BindOnce(&CsisClientImpl::ReadSirkValue,
                                         base::Unretained(instance)));
  }

  uint8_t gatt_if_;
  bluetooth::csis::CsisClientCallbacks* callbacks_;
  std::list<std::shared_ptr<CsisDevice>> devices_;
@@ -2130,6 +2266,7 @@ bool CsisClient::GetForStorage(const RawAddress& addr,

void CsisClient::CleanUp() {
  std::scoped_lock<std::mutex> lock(instance_mutex);
  BTA_DmSirkSecCbRegister(nullptr);
  CsisClientImpl* ptr = instance;
  instance = nullptr;

+8 −0
Original line number Diff line number Diff line
@@ -31,6 +31,14 @@
#include "hardware/bt_gatt_types.h"
#include "test/common/mock_functions.h"

bool gatt_cl_read_sirk_req(
    const RawAddress& peer_bda,
    base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
                            uint8_t sirk_type, Octet16& sirk)>
        cb) {
  return true;
}

namespace bluetooth {
namespace csis {
namespace internal {
+9 −0
Original line number Diff line number Diff line
@@ -271,9 +271,18 @@ class CsisDevice : public GattServiceDevice {
    }
  }

  void SetExpectedGroupIdMember(int group_id) {
    LOG_DEBUG("Expected Group ID: %d, for member: %s is set", group_id,
              ADDRESS_TO_LOGGABLE_CSTR(addr));
    expected_group_id_member = group_id;
  }

  inline int GetExpectedGroupIdMember() { return expected_group_id_member; }

 private:
  /* Instances per start handle  */
  std::map<uint16_t, std::shared_ptr<CsisInstance>> csis_instances_;
  int expected_group_id_member = bluetooth::groups::kGroupUnknown;
};

/*
+42 −1
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ static uint8_t bta_dm_ble_smp_cback(tBTM_LE_EVT event, const RawAddress& bda,
                                    tBTM_LE_EVT_DATA* p_data);
static void bta_dm_ble_id_key_cback(uint8_t key_type,
                                    tBTM_BLE_LOCAL_KEYS* p_key);
static uint8_t bta_dm_sirk_verifiction_cback(const RawAddress& bd_addr);
static void bta_dm_gattc_register(void);
static void btm_dm_start_gatt_discovery(const RawAddress& bd_addr);
static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
@@ -349,7 +350,8 @@ const tBTM_APPL_INFO bta_security = {
    .p_bond_cancel_cmpl_callback = &bta_dm_bond_cancel_complete_cback,
    .p_sp_callback = &bta_dm_sp_cback,
    .p_le_callback = &bta_dm_ble_smp_cback,
    .p_le_key_callback = &bta_dm_ble_id_key_cback};
    .p_le_key_callback = &bta_dm_ble_id_key_cback,
    .p_sirk_verification_callback = &bta_dm_sirk_verifiction_cback};

#define MAX_DISC_RAW_DATA_BUF (4096)
uint8_t g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF];
@@ -367,6 +369,20 @@ void bta_dm_enable(tBTA_DM_SEC_CBACK* p_sec_cback) {
  btm_local_io_caps = btif_storage_get_local_io_caps();
}

void bta_dm_ble_sirk_sec_cb_register(tBTA_DM_SEC_CBACK* p_cback) {
  /* Save the callback to be called when a request of member validation will be
   * needed. */
  LOG_DEBUG("");
  bta_dm_cb.p_sec_sirk_cback = p_cback;
}

void bta_dm_ble_sirk_confirm_device_reply(const RawAddress& bd_addr,
                                          bool accept) {
  LOG_DEBUG("");
  get_btm_client_interface().security.BTM_BleSirkConfirmDeviceReply(
      bd_addr, accept ? BTM_SUCCESS : BTM_NOT_AUTHORIZED);
}

void bta_dm_search_set_state(tBTA_DM_STATE state) {
  bta_dm_search_cb.state = state;
}
@@ -4027,6 +4043,31 @@ static void bta_dm_ble_id_key_cback(uint8_t key_type,
  return;
}

/*******************************************************************************
 *
 * Function         bta_dm_sirk_verifiction_cback
 *
 * Description      SIRK verification when pairing CSIP set member.
 *
 * Returns          void
 *
 ******************************************************************************/
static uint8_t bta_dm_sirk_verifiction_cback(const RawAddress& bd_addr) {
  tBTA_DM_SEC sec_event = {.ble_req = {
                               .bd_addr = bd_addr,
                           }};

  if (bta_dm_cb.p_sec_sirk_cback) {
    LOG_DEBUG("callback called");
    bta_dm_cb.p_sec_sirk_cback(BTA_DM_SIRK_VERIFICATION_REQ_EVT, &sec_event);
    return BTM_CMD_STARTED;
  }

  LOG_DEBUG("no callback registered");

  return BTM_SUCCESS_NO_SECURITY;
}

/*******************************************************************************
 *
 * Function         bta_dm_add_blekey
+37 −0
Original line number Diff line number Diff line
@@ -798,6 +798,43 @@ void BTA_DmBleSubrateRequest(const RawAddress& bd_addr, uint16_t subrate_min,
                               subrate_max, max_latency, cont_num, timeout));
}

/*******************************************************************************
 *
 * Function         BTA_DmSirkSecCbRegister
 *
 * Description      This procedure registeres in requested a callback for
 *                  verification by CSIP potential set member.
 *
 * Parameters       p_cback     - callback to member verificator
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_DmSirkSecCbRegister(tBTA_DM_SEC_CBACK* p_cback) {
  LOG_DEBUG("");
  do_in_main_thread(FROM_HERE,
                    base::Bind(bta_dm_ble_sirk_sec_cb_register, p_cback));
}

/*******************************************************************************
 *
 * Function         BTA_DmSirkConfirmDeviceReply
 *
 * Description      This procedure confirms requested to validate set device.
 *
 * Parameters       bd_addr     - BD address of the peer
 *                  accept      - True if device is authorized by CSIP, false
 *                                otherwise.
 *
 * Returns          void
 *
 ******************************************************************************/
void BTA_DmSirkConfirmDeviceReply(const RawAddress& bd_addr, bool accept) {
  LOG_DEBUG("");
  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ble_sirk_confirm_device_reply,
                                          bd_addr, accept));
}

bool BTA_DmCheckLeAudioCapable(const RawAddress& address) {
  for (tBTM_INQ_INFO* inq_ent = BTM_InqDbFirst(); inq_ent != nullptr;
       inq_ent = BTM_InqDbNext(inq_ent)) {
Loading