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

Commit bcb756ac authored by Venkata Jagadeesh's avatar Venkata Jagadeesh Committed by android-build-merger
Browse files

Merge "Add security handling for LE connection oriented channels" am: 4d024528 am: 74c0f50f

am: 54ed0684

Change-Id: I34cb90a61641ecb1f4baf3cebe67858f032d2ac5
parents 90542901 54ed0684
Loading
Loading
Loading
Loading
+35 −10
Original line number Diff line number Diff line
@@ -1045,12 +1045,12 @@ tBTM_SEC_ACTION btm_ble_determine_security_act(bool is_originator,
 *                  p_callback : Pointer to the callback function.
 *                  p_ref_data : Pointer to be returned along with the callback.
 *
 * Returns          true if link already meets the required security; otherwise
 *                  false.
 * Returns          Returns  - L2CAP LE Connection Response Result Code.
 *
 ******************************************************************************/
bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
                             bool is_originator, tBTM_SEC_CALLBACK* p_callback,
tL2CAP_LE_RESULT_CODE btm_ble_start_sec_check(const RawAddress& bd_addr,
                                              uint16_t psm, bool is_originator,
                                              tBTM_SEC_CALLBACK* p_callback,
                                              void* p_ref_data) {
  /* Find the service record for the PSM */
  tBTM_SEC_SERV_REC* p_serv_rec = btm_sec_find_first_serv(is_originator, psm);
@@ -1060,20 +1060,45 @@ bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
  if (!p_serv_rec) {
    BTM_TRACE_WARNING("%s PSM: %d no application registerd", __func__, psm);
    (*p_callback)(&bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_MODE_UNSUPPORTED);
    return false;
    return L2CAP_LE_RESULT_NO_PSM;
  }
  uint8_t sec_flag = 0;
  BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, BT_TRANSPORT_LE);

  if (!is_originator) {
    if ((p_serv_rec->security_flags & BTM_SEC_IN_ENCRYPT) &&
        !(sec_flag & BTM_SEC_ENCRYPTED)) {
      BTM_TRACE_ERROR(
          "%s: L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP. service "
          "security_flags=0x%x, "
          "sec_flag=0x%x",
          __func__, p_serv_rec->security_flags, sec_flag);
      return L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP;
    } else if ((p_serv_rec->security_flags & BTM_SEC_IN_AUTHENTICATE) &&
               !(sec_flag &
                 (BTM_SEC_LINK_KEY_AUTHED | BTM_SEC_AUTHENTICATED))) {
      BTM_TRACE_ERROR(
          "%s: L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION. service "
          "security_flags=0x%x, "
          "sec_flag=0x%x",
          __func__, p_serv_rec->security_flags, sec_flag);
      return L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION;
    }
    /* TODO: When security is required, then must check that the key size of our
       service is equal or smaller than the incoming connection key size. */
  }

  tBTM_SEC_ACTION sec_act = btm_ble_determine_security_act(
      is_originator, bd_addr, p_serv_rec->security_flags);

  tBTM_BLE_SEC_ACT ble_sec_act = BTM_BLE_SEC_NONE;
  bool status = false;
  tL2CAP_LE_RESULT_CODE result = L2CAP_LE_RESULT_CONN_OK;

  switch (sec_act) {
    case BTM_SEC_OK:
      BTM_TRACE_DEBUG("%s Security met", __func__);
      p_callback(&bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_SUCCESS);
      status = true;
      result = L2CAP_LE_RESULT_CONN_OK;
      break;

    case BTM_SEC_ENCRYPT:
@@ -1096,14 +1121,14 @@ bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
      break;
  }

  if (ble_sec_act == BTM_BLE_SEC_NONE) return status;
  if (ble_sec_act == BTM_BLE_SEC_NONE) return result;

  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
  p_lcb->sec_act = sec_act;
  BTM_SetEncryption(bd_addr, BT_TRANSPORT_LE, p_callback, p_ref_data,
                    ble_sec_act);

  return false;
  return L2CAP_LE_RESULT_CONN_OK;
}

/*******************************************************************************
+4 −4
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@

#include "btm_ble_int.h"
#include "btm_int_types.h"
#include "l2cdefs.h"
#include "smp_api.h"

extern tBTM_CB btm_cb;
@@ -273,10 +274,9 @@ extern bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec,
                                     const RawAddress& new_pseudo_addr);
extern tBTM_SEC_SERV_REC* btm_sec_find_first_serv(CONNECTION_TYPE conn_type,
                                                  uint16_t psm);
extern bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
                                    bool is_originator,
                                    tBTM_SEC_CALLBACK* p_callback,
                                    void* p_ref_data);
extern tL2CAP_LE_RESULT_CODE btm_ble_start_sec_check(
    const RawAddress& bd_addr, uint16_t psm, bool is_originator,
    tBTM_SEC_CALLBACK* p_callback, void* p_ref_data);

extern tINQ_DB_ENT* btm_inq_db_new(const RawAddress& p_bda);

+13 −11
Original line number Diff line number Diff line
@@ -125,18 +125,20 @@
#define L2CAP_CONN_NO_LINK 255
#define L2CAP_CONN_CANCEL 256 /* L2CAP connection cancelled */

/* Define the LE L2CAP connection result codes
/* Define the LE L2CAP Connection Response Result codes
 */
#define L2CAP_LE_CONN_OK 0
#define L2CAP_LE_NO_PSM 2
#define L2CAP_LE_NO_RESOURCES 4
#define L2CAP_LE_INSUFFICIENT_AUTHENTICATION 5
#define L2CAP_LE_INSUFFICIENT_AUTHORIZATION 6
#define L2CAP_LE_INSUFFICIENT_ENCRYP_KEY_SIZE 7
#define L2CAP_LE_INSUFFICIENT_ENCRYP 8
#define L2CAP_LE_RESULT_CONN_OK 0
#define L2CAP_LE_RESULT_NO_PSM 2
#define L2CAP_LE_RESULT_NO_RESOURCES 4
#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION 5
#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION 6
#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE 7
#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP 8
/* We don't like peer device response */
#define L2CAP_LE_INVALID_SOURCE_CID 9
#define L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED 0x0A
#define L2CAP_LE_RESULT_INVALID_SOURCE_CID 9
#define L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED 0x0A

typedef uint8_t tL2CAP_LE_RESULT_CODE;

/* Define L2CAP Move Channel Response result codes
*/
+17 −17
Original line number Diff line number Diff line
@@ -703,8 +703,8 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      if (p_ccb) {
        L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for duplicated cid: 0x%04x",
                            rcid);
        l2cu_reject_ble_connection(p_lcb, id,
                                   L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED);
        l2cu_reject_ble_connection(
            p_lcb, id, L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED);
        break;
      }

@@ -712,7 +712,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
      if (p_rcb == NULL) {
        L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: 0x%04x",
                            con_info.psm);
        l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_NO_PSM);
        l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_NO_PSM);
        break;
      } else {
        if (!p_rcb->api.pL2CA_ConnectInd_Cb) {
@@ -797,7 +797,7 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
            p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
            p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS) {
          L2CAP_TRACE_ERROR("L2CAP don't like the params");
          con_info.l2cap_result = L2CAP_LE_NO_RESOURCES;
          con_info.l2cap_result = L2CAP_LE_RESULT_NO_RESOURCES;
          l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
          break;
        }
@@ -808,13 +808,13 @@ void l2cble_process_sig_cmd(tL2C_LCB* p_lcb, uint8_t* p, uint16_t pkt_len) {
        p_ccb->is_first_seg = true;
        p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;

        if (con_info.l2cap_result == L2CAP_LE_CONN_OK)
        if (con_info.l2cap_result == L2CAP_LE_RESULT_CONN_OK)
          l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
        else
          l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
      } else {
        L2CAP_TRACE_DEBUG("I DO NOT remember the connection req");
        con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID;
        con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
        l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
      }
      break;
@@ -1444,20 +1444,20 @@ void l2cble_sec_comp(const RawAddress* bda, tBT_TRANSPORT transport,
 * Description      This function is called by LE COC link to meet the
 *                  security requirement for the link
 *
 * Returns          true - security procedures are started
 *                  false - failure
 * Returns          Returns  - L2CAP LE Connection Response Result Code.
 *
 ******************************************************************************/
bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm,
                          bool is_originator, tL2CAP_SEC_CBACK* p_callback,
tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr,
                                           uint16_t psm, bool is_originator,
                                           tL2CAP_SEC_CBACK* p_callback,
                                           void* p_ref_data) {
  L2CAP_TRACE_DEBUG("%s", __func__);
  bool status;
  tL2CAP_LE_RESULT_CODE result;
  tL2C_LCB* p_lcb = NULL;

  if (!p_callback) {
    L2CAP_TRACE_ERROR("%s No callback function", __func__);
    return false;
    return L2CAP_LE_RESULT_NO_RESOURCES;
  }

  p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
@@ -1465,14 +1465,14 @@ bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm,
  if (!p_lcb) {
    L2CAP_TRACE_ERROR("%s Security check for unknown device", __func__);
    p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
    return false;
    return L2CAP_LE_RESULT_NO_RESOURCES;
  }

  tL2CAP_SEC_DATA* p_buf =
      (tL2CAP_SEC_DATA*)osi_malloc((uint16_t)sizeof(tL2CAP_SEC_DATA));
  if (!p_buf) {
    p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
    return false;
    return L2CAP_LE_RESULT_NO_RESOURCES;
  }

  p_buf->psm = psm;
@@ -1480,10 +1480,10 @@ bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm,
  p_buf->p_callback = p_callback;
  p_buf->p_ref_data = p_ref_data;
  fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
  status = btm_ble_start_sec_check(bd_addr, psm, is_originator,
  result = btm_ble_start_sec_check(bd_addr, psm, is_originator,
                                   &l2cble_sec_comp, p_ref_data);

  return status;
  return result;
}

/* This function is called to adjust the connection intervals based on various
+16 −4
Original line number Diff line number Diff line
@@ -238,8 +238,19 @@ static void l2c_csm_closed(tL2C_CCB* p_ccb, uint16_t event, void* p_data) {

      if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
        p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
        l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
                             false, &l2c_link_sec_comp2, p_ccb);
        tL2CAP_LE_RESULT_CODE result = l2ble_sec_access_req(
            p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, false,
            &l2c_link_sec_comp2, p_ccb);

        switch (result) {
          case L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION:
          case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE:
          case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP:
            l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id, result);
            l2cu_release_ccb(p_ccb);
            break;
            // TODO: Handle the other return codes
        }
      } else {
        /* Cancel sniff mode if needed */
        {
@@ -442,8 +453,9 @@ static void l2c_csm_term_w4_sec_comp(tL2C_CCB* p_ccb, uint16_t event,
                           l2c_ccb_timer_timeout, p_ccb);
      } else {
        if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
          l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id,
                                     L2CAP_LE_INSUFFICIENT_AUTHENTICATION);
          l2cu_reject_ble_connection(
              p_ccb->p_lcb, p_ccb->remote_id,
              L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION);
        else
          l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
        l2cu_release_ccb(p_ccb);
Loading