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

Commit 21870535 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "Consolidate existing LE connection after pairing"

parents 6e415034 3ce89780
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -1518,13 +1518,30 @@ void btm_ble_ltk_request_reply(const RawAddress& bda, bool use_stk,
  BTM_TRACE_ERROR("key size = %d", p_rec->ble.keys.key_size);
  if (use_stk) {
    btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, stk);
  } else /* calculate LTK using peer device  */
  {
    if (p_rec->ble.key_type & BTM_LE_KEY_LENC)
    return;
  }
  /* calculate LTK using peer device  */
  if (p_rec->ble.key_type & BTM_LE_KEY_LENC) {
    btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p_rec->ble.keys.lltk);
    else
    return;
  }

  p_rec = btm_find_dev_with_lenc(bda);
  if (!p_rec) {
    btsnd_hcic_ble_ltk_req_neg_reply(btm_cb.enc_handle);
    return;
  }

  LOG_INFO("Found second sec_dev_rec for device that have LTK");
  /* This can happen when remote established LE connection using RPA to this
   * device, but then pair with us using Classing transport while still keeping
   * LE connection. If remote attempts to encrypt the LE connection, we might
   * end up here. We will eventually consolidate both entries, this is to avoid
   * race conditions. */

  LOG_ASSERT(p_rec->ble.key_type & BTM_LE_KEY_LENC);
  p_cb->key_size = p_rec->ble.keys.key_size;
  btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p_rec->ble.keys.lltk);
}

/*******************************************************************************
+84 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <string.h>

#include "btm_api.h"
#include "btm_ble_int.h"
#include "device/include/controller.h"
#include "l2c_api.h"
#include "main/shim/btm_api.h"
@@ -372,6 +373,32 @@ tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& bd_addr) {
  return NULL;
}

static bool has_lenc_and_address_is_equal(void* data, void* context) {
  tBTM_SEC_DEV_REC* p_dev_rec = static_cast<tBTM_SEC_DEV_REC*>(data);
  if (!(p_dev_rec->ble.key_type & BTM_LE_KEY_LENC)) return false;

  return is_address_equal(data, context);
}

/*******************************************************************************
 *
 * Function         btm_find_dev_with_lenc
 *
 * Description      Look for the record in the device database with LTK and
 *                  specified BD address
 *
 * Returns          Pointer to the record or NULL
 *
 ******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_dev_with_lenc(const RawAddress& bd_addr) {
  if (btm_cb.sec_dev_rec == nullptr) return nullptr;

  list_node_t* n = list_foreach(btm_cb.sec_dev_rec, has_lenc_and_address_is_equal,
                                (void*)&bd_addr);
  if (n) return static_cast<tBTM_SEC_DEV_REC*>(list_node(n));

  return NULL;
}
/*******************************************************************************
 *
 * Function         btm_consolidate_dev
@@ -429,6 +456,63 @@ void btm_consolidate_dev(tBTM_SEC_DEV_REC* p_target_rec) {
  }
}

/* combine security records of established LE connections after Classic pairing
 * succeeded. */
void btm_dev_consolidate_existing_connections(const RawAddress& bd_addr) {
  tBTM_SEC_DEV_REC* p_target_rec = btm_find_dev(bd_addr);
  if (!p_target_rec) {
    LOG_ERROR("No security record for just bonded device!?!?");
    return;
  }

  if (p_target_rec->ble_hci_handle != HCI_INVALID_HANDLE) {
    LOG_INFO("Not consolidating - already have LE connection");
    return;
  }

  LOG_INFO("%s", ADDRESS_TO_LOGGABLE_CSTR(bd_addr));

  list_node_t* end = list_end(btm_cb.sec_dev_rec);
  list_node_t* node = list_begin(btm_cb.sec_dev_rec);
  while (node != end) {
    tBTM_SEC_DEV_REC* p_dev_rec =
        static_cast<tBTM_SEC_DEV_REC*>(list_node(node));

    // we do list_remove in some cases, must grab next before removing
    node = list_next(node);

    if (p_target_rec == p_dev_rec) continue;

    /* an RPA device entry is a duplicate of the target record */
    if (btm_ble_addr_resolvable(p_dev_rec->bd_addr, p_target_rec)) {
      if (p_dev_rec->ble_hci_handle == HCI_INVALID_HANDLE) {
        LOG_INFO("already disconnected - erasing entry %s",
                 ADDRESS_TO_LOGGABLE_CSTR(p_dev_rec->bd_addr));
        wipe_secrets_and_remove(p_dev_rec);
        continue;
      }

      LOG_INFO(
          "Found existing LE connection to just bonded device on %s handle 0x%04x",
          ADDRESS_TO_LOGGABLE_CSTR(p_dev_rec->bd_addr), p_dev_rec->ble_hci_handle);

      RawAddress ble_conn_addr = p_dev_rec->bd_addr;
      p_target_rec->ble_hci_handle = p_dev_rec->ble_hci_handle;

      /* remove the old LE record */
      wipe_secrets_and_remove(p_dev_rec);

      /* To avoid race conditions between central/peripheral starting encryption
       * at same time, initiate it just from central. */
      if (L2CA_GetBleConnRole(ble_conn_addr) == HCI_ROLE_CENTRAL) {
        LOG_INFO("Will encrypt existing connection");
        BTM_SetEncryption(ble_conn_addr, BT_TRANSPORT_LE, nullptr, nullptr,
                          BTM_BLE_SEC_ENCRYPT);
      }
    }
  }
}

/*******************************************************************************
 *
 * Function         btm_find_or_alloc_dev
+27 −1
Original line number Diff line number Diff line
@@ -109,10 +109,22 @@ bool is_address_equal(void* data, void* context);
 ******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& bd_addr);

/*******************************************************************************
 *
 * Function         btm_find_dev_with_lenc
 *
 * Description      Look for the record in the device database with LTK and
 *                  specified BD address
 *
 * Returns          Pointer to the record or NULL
 *
 ******************************************************************************/
tBTM_SEC_DEV_REC* btm_find_dev_with_lenc(const RawAddress& bd_addr);

/*******************************************************************************
 *
 * Function         btm_consolidate_dev
5**
 *
 * Description      combine security records if identified as same peer
 *
 * Returns          none
@@ -120,6 +132,20 @@ tBTM_SEC_DEV_REC* btm_find_dev(const RawAddress& bd_addr);
 ******************************************************************************/
void btm_consolidate_dev(tBTM_SEC_DEV_REC* p_target_rec);

/*******************************************************************************
 *
 * Function         btm_consolidate_dev
 *
 * Description      When pairing is finished (i.e. on BR/EDR), this function
 *                  checks if there are existing LE connections to same device
 *                  that can now be encrypted and used for profiles requiring
 *                  encryption.
 *
 * Returns          none
 *
 ******************************************************************************/
void btm_dev_consolidate_existing_connections(const RawAddress& bd_addr);

/*******************************************************************************
 *
 * Function         btm_find_or_alloc_dev
+1 −1
Original line number Diff line number Diff line
@@ -1044,7 +1044,7 @@ void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
  tBTM_LE_KEY_VALUE pid_key = {
      .pid_key = {},
  };
  ;

  STREAM_TO_UINT8(pid_key.pid_key.identity_addr_type, p);
  STREAM_TO_BDADDR(pid_key.pid_key.identity_addr, p);
  pid_key.pid_key.irk = p_cb->tk;
+6 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@
#include "stack/include/stack_metrics_logging.h"
#include "types/raw_address.h"

void btm_dev_consolidate_existing_connections(const RawAddress& bd_addr);

#define SMP_PAIRING_REQ_SIZE 7
#define SMP_CONFIRM_CMD_SIZE (OCTET16_LEN + 1)
#define SMP_RAND_CMD_SIZE (OCTET16_LEN + 1)
@@ -1000,6 +1002,10 @@ void smp_proc_pairing_cmpl(tSMP_CB* p_cb) {
                          metric_status);
  }

  if (p_cb->status == SMP_SUCCESS && p_cb->smp_over_br) {
    btm_dev_consolidate_existing_connections(pairing_bda);
  }

  smp_reset_control_value(p_cb);

  if (p_callback) (*p_callback)(SMP_COMPLT_EVT, pairing_bda, &evt_data);
Loading