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

Commit 2711c1ab authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

DO NOT MERGE Drop Bluetooth connection with weak encryption key

This patch requires Bluetooth chip to support HCI Read Encryption Key Size
command and will cause Bluetooth to crash if this command is not supported
on a device. Such device should not take this patch and should look for
alternative solution to drop Bluetooth connection with weak encryption key.

Bug: 124301137
Change-Id: Id4b6b4e765628397a79e6806f45c2cd27acebd5b
parent e9697303
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -252,6 +252,8 @@ static future_t *start_up(void) {
        &number_of_local_supported_codecs, local_supported_codecs);
  }

  assert(HCI_READ_ENCR_KEY_SIZE_SUPPORTED(supported_commands));

  readable = true;
  return future_new_immediate(FUTURE_SUCCESS);
}
+85 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#define LOG_TAG "bt_btu_hcif"

#include <assert.h>
#include <log/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -601,6 +602,55 @@ static void btu_hcif_rmt_name_request_comp_evt (UINT8 *p, UINT16 evt_len)
    btm_sec_rmt_name_request_complete (bd_addr, p, status);
}

const uint8_t MIN_KEY_SIZE = 7;
bool read_key_send_from_key_refresh = false;

static void read_encryption_key_size_complete_after_key_refresh(
    uint8_t status, uint16_t handle, uint8_t key_size) {
  if (status != HCI_SUCCESS) {
    HCI_TRACE_WARNING("%s: disconnecting, status: 0x%02x", __func__, status);
    btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
    return;
  }

  if (key_size < MIN_KEY_SIZE) {
    android_errorWriteLog(0x534e4554, "124301137");
    HCI_TRACE_ERROR(
        "%s encryption key too short, disconnecting. handle: 0x%02x, key_size: "
        "%d",
        __func__, handle, key_size);

    btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
    return;
  }

  btm_sec_encrypt_change(handle, status, 1 /* enc_enable */);
}

static void read_encryption_key_size_complete_after_encryption_change(
    uint8_t status, uint16_t handle, uint8_t key_size) {
  if (status != HCI_SUCCESS) {
    HCI_TRACE_WARNING("%s: disconnecting, status: 0x%02x", __func__, status);
    btsnd_hcic_disconnect(handle, HCI_ERR_PEER_USER);
    return;
  }

  if (key_size < MIN_KEY_SIZE) {
    android_errorWriteLog(0x534e4554, "124301137");
    HCI_TRACE_ERROR(
        "%s encryption key too short, disconnecting. handle: 0x%02x, key_size: "
        "%d",
        __func__, handle, key_size);

    btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
    return;
  }

  // good key size - succeed
  btm_acl_encrypt_change(handle, status, 1 /* enable */);
  btm_sec_encrypt_change(handle, status, 1 /* enable */);
}

/*******************************************************************************
**
** Function         btu_hcif_encryption_change_evt
@@ -620,8 +670,14 @@ static void btu_hcif_encryption_change_evt (UINT8 *p)
    STREAM_TO_UINT16 (handle, p);
    STREAM_TO_UINT8  (encr_enable, p);

    if (status != HCI_SUCCESS || encr_enable == 0 ||
        BTM_IsBleConnection(handle)) {
        btm_acl_encrypt_change (handle, status, encr_enable);
        btm_sec_encrypt_change (handle, status, encr_enable);
    } else {
        read_key_send_from_key_refresh = false;
        btsnd_hcic_read_encryption_key_size(handle);
    }
}

/*******************************************************************************
@@ -824,6 +880,26 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
            btm_read_inq_tx_power_complete(p);
            break;

        case HCI_READ_ENCR_KEY_SIZE: {
            UINT8 *pp = p;

            UINT8   status;
            UINT16  handle;
            UINT8   key_size;

            STREAM_TO_UINT8  (status, pp);
            STREAM_TO_UINT16 (handle, pp);
            STREAM_TO_UINT8  (key_size, pp);

            if (read_key_send_from_key_refresh) {
                read_encryption_key_size_complete_after_encryption_change(status, handle, key_size);
            } else {
                read_encryption_key_size_complete_after_key_refresh(status, handle, key_size);
            }

            }
            break;

#if (BLE_INCLUDED == TRUE)
/* BLE Commands sComplete*/
        case HCI_BLE_ADD_WHITE_LIST:
@@ -1595,6 +1671,7 @@ static void btu_hcif_enhanced_flush_complete_evt (void)
** BLE Events
***********************************************/
#if (defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE)

static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p)
{
    UINT8   status;
@@ -1606,7 +1683,12 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p)

    if (status == HCI_SUCCESS) enc_enable = 1;

    if (status != HCI_SUCCESS || BTM_IsBleConnection(handle)) {
        btm_sec_encrypt_change (handle, status, enc_enable);
    } else  {
        read_key_send_from_key_refresh = true;
        btsnd_hcic_read_encryption_key_size(handle);
    }
}

static void btu_ble_process_adv_pkt (UINT8 *p)
+13 −0
Original line number Diff line number Diff line
@@ -1356,6 +1356,19 @@ BOOLEAN btsnd_hcic_read_rssi (UINT16 handle)
    return (TRUE);
}

BOOLEAN btsnd_hcic_read_encryption_key_size(UINT16 handle) {
    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
    UINT8 *pp = (UINT8 *)(p + 1);

    p->len    = HCIC_PREAMBLE_SIZE + 2;
    p->offset = 0;

    UINT16_TO_STREAM (pp, handle);

    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
    return (TRUE);
}

BOOLEAN btsnd_hcic_enable_test_mode (void)
{
    BT_HDR *p = (BT_HDR *)osi_malloc(HCI_CMD_BUF_SIZE);
+11 −1
Original line number Diff line number Diff line
@@ -1288,7 +1288,17 @@ extern BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig,
extern void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr,
                                            tBLE_ADDR_TYPE *p_addr_type);


/*******************************************************************************
 *
 * Function         BTM_IsBleConnection
 *
 * Description      This function is called to check if the connection handle
 *                  for an LE link
 *
 * Returns          true if connection is LE link, otherwise false.
 *
 ******************************************************************************/
extern bool BTM_IsBleConnection(uint16_t conn_handle);

/*******************************************************************************
**
+1 −0
Original line number Diff line number Diff line
@@ -603,6 +603,7 @@ extern BOOLEAN btsnd_hcic_write_cur_iac_lap (UINT8 num_cur_iac,

extern BOOLEAN btsnd_hcic_get_link_quality (UINT16 handle);            /* Get Link Quality */
extern BOOLEAN btsnd_hcic_read_rssi (UINT16 handle);                   /* Read RSSI */
extern BOOLEAN btsnd_hcic_read_encryption_key_size (UINT16 handle);    /* Read encryption key size */
extern BOOLEAN btsnd_hcic_enable_test_mode (void);                     /* Enable Device Under Test Mode */
extern BOOLEAN btsnd_hcic_write_pagescan_type(UINT8 type);             /* Write Page Scan Type */
extern BOOLEAN btsnd_hcic_write_inqscan_type(UINT8 type);              /* Write Inquiry Scan Type */