Cross transport key mapping fixes
Change-Id: I22d97303054eccc876c4a9c7c0a50e369ff4fa62
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index c72ed3f..8201c57 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -125,11 +125,10 @@
BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
(char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
}
- p_dev_rec->device_type = dev_type;
+ p_dev_rec->device_type |= dev_type;
p_dev_rec->ble.ble_addr_type = addr_type;
- BTM_TRACE_DEBUG ("p_dev_rec->device_type =0x%x addr_type=0x%x sec_flags=0x%x",
- dev_type, addr_type, p_dev_rec->sec_flags);
+ memcpy (p_dev_rec->ble.pseudo_addr, bd_addr, BD_ADDR_LEN);
/* sync up with the Inq Data base*/
p_info = BTM_InqDbRead(bd_addr);
if (p_info)
@@ -1395,7 +1394,7 @@
}
/* to notify GATT to send data if any request is pending */
- gatt_notify_enc_cmpl(p_dev_rec->bd_addr);
+ gatt_notify_enc_cmpl(p_dev_rec->ble.pseudo_addr);
}
/*******************************************************************************
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 142b8d8..b3a3b33 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -262,6 +262,74 @@
}
return FALSE;
}
+
+/*******************************************************************************
+**
+** Function btm_ble_init_pseudo_addr
+**
+** Description This function is used to initialize pseudo address.
+** If pseudo address is not available, use dummy address
+**
+** Returns TRUE is updated; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr)
+{
+ BD_ADDR dummy_bda = {0};
+
+ if (memcmp(p_dev_rec->ble.pseudo_addr, dummy_bda, BD_ADDR_LEN) == 0)
+ {
+ memcpy(p_dev_rec->ble.pseudo_addr, new_pseudo_addr, BD_ADDR_LEN);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_addr_resolvable
+**
+** Description This function checks if a RPA is resolvable by the device key.
+**
+** Returns TRUE is resolvable; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_addr_resolvable (BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec)
+{
+ BOOLEAN rt = FALSE;
+
+ if (!BTM_BLE_IS_RESOLVE_BDA(rpa))
+ return rt;
+
+ UINT8 rand[3];
+ tSMP_ENC output;
+ if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
+ (p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
+ {
+ BTM_TRACE_DEBUG("%s try to resolve", __func__);
+ /* use the 3 MSB of bd address as prand */
+ rand[0] = rpa[2];
+ rand[1] = rpa[1];
+ rand[2] = rpa[0];
+
+ /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
+ SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN,
+ &rand[0], 3, &output);
+
+ rand[0] = rpa[5];
+ rand[1] = rpa[4];
+ rand[2] = rpa[3];
+
+ if (!memcmp(output.param_buf, &rand[0], 3))
+ {
+ btm_ble_init_pseudo_addr (p_dev_rec, rpa);
+ rt = TRUE;
+ }
+ }
+ return rt;
+}
+
/*******************************************************************************
**
** Function btm_ble_match_random_bda
@@ -276,23 +344,24 @@
static BOOLEAN btm_ble_match_random_bda(UINT16 rec_index)
{
#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
- tBTM_SEC_DEV_REC *p_dev_rec;
- tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
- UINT8 rand[3];
- tSMP_ENC output;
-
/* use the 3 MSB of bd address as prand */
+
+ tBTM_LE_RANDOM_CB *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+ UINT8 rand[3];
rand[0] = p_mgnt_cb->random_bda[2];
rand[1] = p_mgnt_cb->random_bda[1];
rand[2] = p_mgnt_cb->random_bda[0];
- BTM_TRACE_EVENT("btm_ble_match_random_bda rec_index = %d", rec_index);
+ BTM_TRACE_EVENT("%s rec_index = %d", __func__, rec_index);
if (rec_index < BTM_SEC_MAX_DEVICE_RECORDS)
{
+ tSMP_ENC output;
+ tBTM_SEC_DEV_REC *p_dev_rec;
p_dev_rec = &btm_cb.sec_dev_rec[rec_index];
- BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags, p_dev_rec->device_type);
+ BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags,
+ p_dev_rec->device_type);
if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
(p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
@@ -370,7 +439,7 @@
tBTM_SEC_DEV_REC *p_dev_rec = NULL;
BTM_TRACE_EVENT ("btm_ble_map_bda_to_conn_bda");
if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL &&
- p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+ (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
{
if (p_dev_rec->ble.ble_addr_type != BLE_ADDR_PUBLIC)
{
@@ -439,8 +508,12 @@
/* assign the original address to be the current report address */
memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
- *p_addr_type = p_dev_rec->ble.ble_addr_type;
+ /* assign the original address to be the current report address */
+ if (!btm_ble_init_pseudo_addr (p_dev_rec, bd_addr))
+ memcpy(bd_addr, p_dev_rec->ble.pseudo_addr, BD_ADDR_LEN);
+
+ *p_addr_type = p_dev_rec->ble.ble_addr_type;
return TRUE;
}
#endif
@@ -487,8 +560,8 @@
UINT8 rra_type)
{
#if BLE_PRIVACY_SPT == TRUE
- UINT8 rra_dummy = FALSE;
- BD_ADDR dummy_bda = {0};
+ UINT8 rra_dummy = FALSE;
+ BD_ADDR dummy_bda = {0};
if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0)
rra_dummy = TRUE;
@@ -515,7 +588,10 @@
__func__, p_sec_rec->ble.active_addr_type);
/* connection refresh remote address */
- tACL_CONN *p_acl = p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+ tACL_CONN *p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+ if (p_acl == NULL)
+ p_acl = btm_bda_to_acl(p_sec_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
+
if (p_acl != NULL)
{
if (rra_type == BTM_BLE_ADDR_PSEUDO)
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 46953db..8912c25 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -2654,8 +2654,10 @@
{
/* new device */
if (p_i == NULL ||
- (/* assume a DUMO device, BR/EDR inquiry is always active */
- p_i && p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE && p_i->scan_rsp))
+ /* assume a DUMO device, BR/EDR inquiry is always active */
+ (p_i &&
+ (p_i->inq_info.results.device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE &&
+ p_i->scan_rsp))
{
BTM_TRACE_WARNING("INQ RES: Extra Response Received...cancelling inquiry..");
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 9d5c493..adf0837 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -290,42 +290,43 @@
/*****************************************************
** BLE Inquiry
*****************************************************/
- tBTM_BLE_INQ_CB inq_var;
+ tBTM_BLE_INQ_CB inq_var;
/* observer callback and timer */
tBTM_INQ_RESULTS_CB *p_obs_results_cb;
- tBTM_CMPL_CB *p_obs_cmpl_cb;
- TIMER_LIST_ENT obs_timer_ent;
+ tBTM_CMPL_CB *p_obs_cmpl_cb;
+ TIMER_LIST_ENT obs_timer_ent;
/* background connection procedure cb value */
- tBTM_BLE_CONN_TYPE bg_conn_type;
- UINT16 scan_int;
- UINT16 scan_win;
- tBTM_BLE_SEL_CBACK *p_select_cback;
+ tBTM_BLE_CONN_TYPE bg_conn_type;
+ UINT16 scan_int;
+ UINT16 scan_win;
+ tBTM_BLE_SEL_CBACK *p_select_cback;
/* white list information */
UINT8 white_list_avail_size;
tBTM_BLE_WL_STATE wl_state;
- BUFFER_Q conn_pending_q;
- tBTM_BLE_CONN_ST conn_state;
+ BUFFER_Q conn_pending_q;
+ tBTM_BLE_CONN_ST conn_state;
/* random address management control block */
- tBTM_LE_RANDOM_CB addr_mgnt_cb;
+ tBTM_LE_RANDOM_CB addr_mgnt_cb;
- BOOLEAN enabled;
+ BOOLEAN enabled;
#if BLE_PRIVACY_SPT == TRUE
- BOOLEAN mixed_mode; /* privacy 1.2 mixed mode is on or not */
- tBTM_PRIVACY_MODE privacy_mode; /* privacy mode */
- UINT8 resolving_list_avail_size; /* resolving list available size */
- tBTM_BLE_RESOLVE_Q resolving_list_pend_q;
+ BOOLEAN mixed_mode; /* privacy 1.2 mixed mode is on or not */
+ tBTM_PRIVACY_MODE privacy_mode; /* privacy mode */
+ UINT8 resolving_list_avail_size; /* resolving list available size */
+ UINT8 *irk_list_mask; /* IRK list availability mask, up to max entry bits */
+ tBTM_BLE_RESOLVE_Q resolving_list_pend_q;
#endif
- tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
+ tBTM_BLE_WL_OP wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
/* current BLE link state */
- tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
- UINT8 link_count[2]; /* total link count master and slave*/
+ tBTM_BLE_STATE_MASK cur_states; /* bit mask of tBTM_BLE_STATE */
+ UINT8 link_count[2]; /* total link count master and slave*/
} tBTM_BLE_CB;
#ifdef __cplusplus
diff --git a/stack/btm/btm_ble_privacy.c b/stack/btm/btm_ble_privacy.c
index b905eac..9174116 100644
--- a/stack/btm/btm_ble_privacy.c
+++ b/stack/btm/btm_ble_privacy.c
@@ -62,13 +62,12 @@
** Returns void
**
*******************************************************************************/
-void btm_ble_enq_resolving_list_pending(BD_ADDR psuedo_bda, UINT8 op_code)
+void btm_ble_enq_resolving_list_pending(BD_ADDR pseudo_bda, UINT8 op_code)
{
- tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
- memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
+ memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], pseudo_bda, BD_ADDR_LEN);
p_q->resolve_q_action[p_q->q_next] = op_code;
-
p_q->q_next ++;
p_q->q_next %= controller_get_interface()->get_ble_resolving_list_max_size();
}
@@ -85,13 +84,13 @@
** Returns void
**
*******************************************************************************/
-BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
+BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR pseudo_addr, UINT8 action)
{
tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
- for (UINT8 i = p_q->q_pending; i != p_q->q_next; )
+ for (UINT8 i = p_q->q_pending; i != p_q->q_next;)
{
- if (memcmp(p_q->resolve_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
+ if (memcmp(p_q->resolve_q_random_pseudo[i], pseudo_addr, BD_ADDR_LEN) == 0 &&
action == p_q->resolve_q_action[i])
return TRUE;
@@ -107,52 +106,83 @@
**
** Description dequeue target address from resolving pending operation queue
**
-** Parameters psuedo_addr: psuedo_addr device address
+** Parameters pseudo_addr: pseudo_addr device address
**
** Returns void
**
*******************************************************************************/
-BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR psuedo_addr)
+BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR pseudo_addr)
{
tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
if (p_q->q_next != p_q->q_pending)
{
- memcpy(psuedo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
+ memcpy(pseudo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
memset(p_q->resolve_q_random_pseudo[p_q->q_pending], 0, BD_ADDR_LEN);
-
p_q->q_pending ++;
p_q->q_pending %= controller_get_interface()->get_ble_resolving_list_max_size();
-
return TRUE;
}
+
return FALSE;
}
/*******************************************************************************
**
-** Function btm_ble_find_resolving_list_entry
+** Function btm_ble_clear_irk_index
**
-** Description find the device record if the pseudo address is currently in
-** the resolving list
+** Description clear IRK list index mask for availability
**
-** Returns pointer to the security device record; NULL otherwise
+** Returns none
**
*******************************************************************************/
-tBTM_SEC_DEV_REC * btm_ble_find_resolving_list_entry(BD_ADDR pseudo_bda)
+void btm_ble_clear_irk_index(UINT8 index)
{
- tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+ UINT8 byte;
+ UINT8 bit;
for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec++)
{
- if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
- (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
- memcmp(p_dev_rec->bd_addr, pseudo_bda, BD_ADDR_LEN) == 0)
+ if (index < controller_get_interface()->get_ble_resolving_list_max_size())
{
- return p_dev_rec ;
+ byte = index / 8;
+ bit = index % 8;
+ btm_cb.ble_ctr_cb.irk_list_mask[byte] &= (~(1 << bit));
}
}
- return NULL;
+}
+
+/*******************************************************************************
+**
+** Function btm_ble_find_irk_index
+**
+** Description find the first available IRK list index
+**
+** Returns index from 0 ~ max (127 default)
+**
+*******************************************************************************/
+UINT8 btm_ble_find_irk_index(void)
+{
+ UINT8 i = 0;
+ UINT8 byte;
+ UINT8 bit;
+
+ while (i < controller_get_interface()->get_ble_resolving_list_max_size())
+ {
+ byte = i / 8;
+ bit = i % 8;
+
+ if ((btm_cb.ble_ctr_cb.irk_list_mask[byte] & (1 << bit)) == 0)
+ {
+ btm_cb.ble_ctr_cb.irk_list_mask[byte] |= (1 << bit);
+ return i;
+ }
+ i++;
+ }
+
+ BTM_TRACE_ERROR ("%s failed, list full", __func__);
+ return i;
}
/*******************************************************************************
@@ -166,21 +196,25 @@
*******************************************************************************/
void btm_ble_update_resolving_list(BD_ADDR pseudo_bda, BOOLEAN add)
{
- tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (pseudo_bda);
-
+ tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_bda);
if (p_dev_rec == NULL)
return;
if (add)
{
p_dev_rec->ble.in_controller_list |= BTM_RESOLVING_LIST_BIT;
- /* set resolving list entry index : = max- available - 1*/
- p_dev_rec->ble.resolving_list_index =
- controller_get_interface()->get_ble_resolving_list_max_size() -
- btm_cb.ble_ctr_cb.resolving_list_avail_size - 1;
- } else {
+ if (!controller_get_interface()->supports_ble_privacy())
+ p_dev_rec->ble.resolving_list_index = btm_ble_find_irk_index();
+ }
+ else
+ {
p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
- p_dev_rec->ble.resolving_list_index = 0;
+ if (!controller_get_interface()->supports_ble_privacy())
+ {
+ /* clear IRK list index mask */
+ btm_ble_clear_irk_index(p_dev_rec->ble.resolving_list_index);
+ p_dev_rec->ble.resolving_list_index = 0;
+ }
}
}
@@ -196,31 +230,37 @@
*******************************************************************************/
void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len)
{
- UINT8 status;
+ UINT8 status = 0;
STREAM_TO_UINT8(status, p);
- BTM_TRACE_DEBUG("%s status = %d", __func__, status);
-
- /* standard HCI status only have one status byte, if greater than 3, VSC complete received */
- if (evt_len >= 3)
- {
- /* VSC complete has one extra byte for op code and list size, skip it here */
- p ++;
- /* updated the available list size, and current list size */
- UINT8 max_resolving_list_size;
- STREAM_TO_UINT8(max_resolving_list_size, p);
- controller_get_interface()->set_ble_resolving_list_max_size(max_resolving_list_size);
- }
+ BTM_TRACE_DEBUG("%s status=%d", __func__, status);
if (status == HCI_SUCCESS)
{
- btm_cb.ble_ctr_cb.resolving_list_avail_size =
+ if (evt_len >= 3)
+ {
+ /* VSC complete has one extra byte for op code and list size, skip it here */
+ p ++;
+
+ /* updated the available list size, and current list size */
+ uint8_t irk_list_sz_max = 0;
+ STREAM_TO_UINT8(irk_list_sz_max, p);
+
+ if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+ btm_ble_resolving_list_init(irk_list_sz_max);
+
+ uint8_t irk_mask_size = (irk_list_sz_max % 8) ?
+ (irk_list_sz_max / 8 + 1) : (irk_list_sz_max / 8);
+ memset(btm_cb.ble_ctr_cb.irk_list_mask, 0, irk_mask_size);
+ }
+
+ btm_cb.ble_ctr_cb.resolving_list_avail_size =
controller_get_interface()->get_ble_resolving_list_max_size();
- BTM_TRACE_DEBUG("%s resolving_list_avail_size = %d",
+ BTM_TRACE_DEBUG("%s resolving_list_avail_size=%d",
__func__, btm_cb.ble_ctr_cb.resolving_list_avail_size);
- for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
+ for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; ++i)
btm_cb.sec_dev_rec[i].ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
}
}
@@ -237,13 +277,13 @@
*******************************************************************************/
void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
{
- UINT8 status;
+ UINT8 status;
STREAM_TO_UINT8(status, p);
BTM_TRACE_DEBUG("%s status = %d", __func__, status);
BD_ADDR pseudo_bda;
- if (!btm_ble_deq_resolving_pending( pseudo_bda))
+ if (!btm_ble_deq_resolving_pending(pseudo_bda))
{
BTM_TRACE_DEBUG("no pending resolving list operation");
return;
@@ -260,7 +300,6 @@
}
else
btm_cb.ble_ctr_cb.resolving_list_avail_size --;
-
}
else if (status == HCI_ERR_MEMORY_FULL) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED */
{
@@ -281,10 +320,10 @@
*******************************************************************************/
void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
{
- BD_ADDR pseudo_bda;
+ BD_ADDR pseudo_bda;
+ UINT8 status;
- UINT8 status;
- STREAM_TO_UINT8 (status, p);
+ STREAM_TO_UINT8(status, p);
BTM_TRACE_DEBUG("%s status = %d", __func__, status);
@@ -299,14 +338,14 @@
/* proprietary: spec does not have these extra bytes */
if (evt_len > 2)
{
- p ++; /* skip opcode */
+ p ++; /* skip opcode */
STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
}
else
- btm_cb.ble_ctr_cb.resolving_list_avail_size ++;
-
+ btm_cb.ble_ctr_cb.resolving_list_avail_size++;
}
}
+
/*******************************************************************************
**
** Function btm_ble_read_resolving_list_entry_complete
@@ -409,14 +448,19 @@
*******************************************************************************/
tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
{
- tBTM_STATUS st = BTM_NO_RESOURCES;
+ /* if controller does not support RPA offloading or privacy 1.2, skip */
+ if (controller_get_interface()->get_ble_resolving_list_max_size())
+ return BTM_WRONG_MODE;
+ tBTM_STATUS st = BTM_NO_RESOURCES;
if (controller_get_interface()->supports_ble_privacy())
{
- if (btsnd_hcic_ble_rm_device_resolving_list (p_dev_rec->ble.static_addr_type,
- p_dev_rec->ble.static_addr))
+ if (btsnd_hcic_ble_rm_device_resolving_list(p_dev_rec->ble.static_addr_type,
+ p_dev_rec->ble.static_addr))
st = BTM_CMD_STARTED;
- } else {
+ }
+ else
+ {
UINT8 param[20]= {0};
UINT8 *p = param;
@@ -424,16 +468,14 @@
UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
- st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_REMOVE_IRK_LEN,
- param,
- btm_ble_resolving_list_vsc_op_cmpl);
+ st = BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC,
+ BTM_BLE_META_REMOVE_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl);
}
if (st == BTM_CMD_STARTED)
- {
btm_ble_enq_resolving_list_pending( p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY);
- }
return st;
}
@@ -494,8 +536,8 @@
if (controller_get_interface()->supports_ble_privacy())
{
if (btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.static_addr_type,
- p_dev_rec->ble.static_addr))
- st = BTM_CMD_STARTED;
+ p_dev_rec->ble.static_addr))
+ st = BTM_CMD_STARTED;
}
else
{
@@ -512,9 +554,8 @@
}
if (st == BTM_CMD_STARTED)
- {
- btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr, BTM_BLE_META_READ_IRK_ENTRY);
- }
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_READ_IRK_ENTRY);
return st;
}
@@ -532,28 +573,31 @@
*******************************************************************************/
BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
{
- BOOLEAN rt = FALSE;
- tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
+ BOOLEAN rt = FALSE;
BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
- btm_cb.ble_ctr_cb.privacy_mode);
+ btm_cb.ble_ctr_cb.privacy_mode);
+ /* if controller does not support RPA offloading or privacy 1.2, skip */
+ if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+ return FALSE;
+
+ BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d",
+ __func__, btm_cb.ble_ctr_cb.privacy_mode);
+
+ /* only add RPA enabled device into resolving list */
if (p_dev_rec != NULL && /* RPA is being used and PID is known */
p_dev_rec->sec_flags & BTM_SEC_IN_USE &&
- /* only add RPA enabled device into resolving list */
- (((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0
- && BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
- || ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0
- && btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
+ ((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0 ||
+ ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0 &&
+ btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
{
if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
BTM_BLE_META_ADD_IRK_ENTRY) == FALSE)
{
- if (p_cb->resolving_list_avail_size > 0)
+ if (btm_cb.ble_ctr_cb.resolving_list_avail_size > 0)
{
- btm_ble_update_resolving_list( p_dev_rec->bd_addr, TRUE);
-
+ btm_ble_update_resolving_list(p_dev_rec->bd_addr, TRUE);
if (controller_get_interface()->supports_ble_privacy())
{
UINT8 dummy_irk[HCIC_BLE_IRK_SIZE];
@@ -561,9 +605,9 @@
UINT8 *peer_irk;
if (BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
- peer_irk = p_dev_rec->ble.keys.irk;
+ peer_irk = p_dev_rec->ble.keys.irk;
else
- peer_irk = dummy_irk;
+ peer_irk = dummy_irk;
UINT8 *local_irk;
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
@@ -573,17 +617,29 @@
BD_ADDR dummy_bda = {0};
/* for device not assigning static address, use pseudo address as identity */
+ peer_irk = p_dev_rec->ble.keys.irk;
+ local_irk = btm_cb.devcb.id_keys.irk;
+
+ // do not enter IRK if peer or local device does not have privacy turned on
+ // disable, assume IRK indicate privacy could be enabled at any point,
+ // warning: this could take up unnecessary spot in controller resolving list,
+ // and could possible degrade performance; this could prevent conneccting
+ // to peripheral device which has privacy disabled but IRK delivered per
+ // standard privacy 1.2 requirement. Need FW mixed mode support to connect
+ // to both RPA and static address.
if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) == 0)
{
memcpy(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
}
+ BTM_TRACE_DEBUG("%s:adding device to controller resolving list", __func__);
+ // use identical IRK for now
rt = btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
- p_dev_rec->ble.static_addr, peer_irk, local_irk); // use identical IRK for now
+ p_dev_rec->ble.static_addr, peer_irk, local_irk);
}
- else
- {
+ else
+ {
UINT8 param[40] = {0};
UINT8 *p = param;
@@ -593,16 +649,16 @@
BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
- BTM_BLE_META_ADD_IRK_LEN,
- param,
- btm_ble_resolving_list_vsc_op_cmpl)
- == BTM_CMD_STARTED)
+ BTM_BLE_META_ADD_IRK_LEN,
+ param,
+ btm_ble_resolving_list_vsc_op_cmpl)
+ == BTM_CMD_STARTED)
rt = TRUE;
- }
+ }
if (rt)
- btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
- BTM_BLE_META_ADD_IRK_ENTRY);
+ btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+ BTM_BLE_META_ADD_IRK_ENTRY);
}
}
else
@@ -631,14 +687,17 @@
*******************************************************************************/
void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
{
- btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
+ btm_ble_update_resolving_list(p_dev_rec->bd_addr, FALSE);
if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
BTM_BLE_META_REMOVE_IRK_ENTRY) == FALSE)
{
+ btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
btm_ble_remove_resolving_list_entry(p_dev_rec);
- } else {
+ }
+ else
+ {
BTM_TRACE_DEBUG("Device not in resolving list");
}
}
@@ -679,6 +738,10 @@
*******************************************************************************/
void btm_ble_disable_resolving_list(void)
{
+ /* if controller does not support RPA offloading or privacy 1.2, skip */
+ if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+ return;
+
if (btm_cb.ble_ctr_cb.enabled)
{
if (!controller_get_interface()->supports_ble_privacy())
@@ -725,7 +788,7 @@
BOOLEAN btm_ble_resolving_list_empty(void)
{
return (controller_get_interface()->get_ble_resolving_list_max_size() ==
- btm_cb.ble_ctr_cb.resolving_list_avail_size);
+ btm_cb.ble_ctr_cb.resolving_list_avail_size);
}
/*******************************************************************************
@@ -752,7 +815,6 @@
btm_ble_enable_resolving_list();
else
btm_ble_disable_resolving_list();
-
return;
}
@@ -782,13 +844,18 @@
*******************************************************************************/
void btm_ble_resolving_list_init(UINT8 max_irk_list_sz)
{
- tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+ UINT8 irk_mask_size = (max_irk_list_sz % 8) ?
+ (max_irk_list_sz/8 + 1) : (max_irk_list_sz/8);
if (max_irk_list_sz > 0)
{
- p_q->resolve_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
- max_irk_list_sz);
- p_q->resolve_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
+ p_q->resolve_q_random_pseudo = (BD_ADDR *)GKI_getbuf(sizeof(BD_ADDR) * max_irk_list_sz);
+ p_q->resolve_q_action = (UINT8 *)GKI_getbuf(max_irk_list_sz);
+
+ /* RPA offloading feature */
+ if (btm_cb.ble_ctr_cb.irk_list_mask == NULL)
+ btm_cb.ble_ctr_cb.irk_list_mask = (UINT8 *)GKI_getbuf(irk_mask_size);
BTM_TRACE_DEBUG ("%s max_irk_list_sz = %d", __func__, max_irk_list_sz);
}
@@ -810,7 +877,7 @@
*******************************************************************************/
void btm_ble_resolving_list_cleanup(void)
{
- tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+ tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
if (p_q->resolve_q_random_pseudo)
GKI_freebuf(p_q->resolve_q_random_pseudo);
@@ -819,5 +886,9 @@
GKI_freebuf(p_q->resolve_q_action);
controller_get_interface()->set_ble_resolving_list_max_size(0);
+ if (btm_cb.ble_ctr_cb.irk_list_mask)
+ GKI_freebuf(btm_cb.ble_ctr_cb.irk_list_mask);
+
+ btm_cb.ble_ctr_cb.irk_list_mask = NULL;
}
#endif
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 3053dbe..faae4f5 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -155,6 +155,7 @@
#endif
p_dev_rec->rmt_io_caps = io_cap;
+ p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
return(TRUE);
}
@@ -427,18 +428,26 @@
** Returns Pointer to the record or NULL
**
*******************************************************************************/
-tBTM_SEC_DEV_REC *btm_find_dev (BD_ADDR bd_addr)
+tBTM_SEC_DEV_REC *btm_find_dev(BD_ADDR bd_addr)
{
tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
- int i;
if (bd_addr)
{
- for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+ for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
{
- if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
- && (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN)))
- return(p_dev_rec);
+ if (p_dev_rec->sec_flags & BTM_SEC_IN_USE)
+ {
+ if (!memcmp (p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN))
+ return(p_dev_rec);
+
+ // If a LE random address is looking for device record
+ if (!memcmp(p_dev_rec->ble.pseudo_addr, bd_addr, BD_ADDR_LEN))
+ return (p_dev_rec);
+
+ if (btm_ble_addr_resolvable(bd_addr, p_dev_rec))
+ return(p_dev_rec);
+ }
}
}
return(NULL);
@@ -446,6 +455,59 @@
/*******************************************************************************
**
+** Function btm_consolidate_dev
+**
+** Description combine security records if identified as same peer
+**
+** Returns none
+**
+*******************************************************************************/
+void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec)
+{
+ tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+ tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
+ BD_ADDR dummy_bda = {0};
+
+ BTM_TRACE_DEBUG("%s", __func__);
+
+ for (uint8_t i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+ {
+ if (p_target_rec!= p_dev_rec && p_dev_rec->sec_flags & BTM_SEC_IN_USE)
+ {
+ if (!memcmp (p_dev_rec->bd_addr, p_target_rec->bd_addr, BD_ADDR_LEN))
+ {
+ memcpy(p_target_rec, p_dev_rec, sizeof(tBTM_SEC_DEV_REC));
+ p_target_rec->ble = temp_rec.ble;
+ p_target_rec->enc_key_size = temp_rec.enc_key_size;
+ p_target_rec->ble_hci_handle = temp_rec.ble_hci_handle;
+ p_target_rec->conn_params = temp_rec.conn_params;
+ p_target_rec->device_type |= temp_rec.device_type;
+ p_target_rec->sec_flags |= temp_rec.sec_flags;
+
+ p_target_rec->new_encryption_key_is_p256 = temp_rec.new_encryption_key_is_p256;
+ p_target_rec->no_smp_on_br = temp_rec.no_smp_on_br;
+ /* mark the combined record as unused */
+ p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
+ break;
+ }
+
+ /* 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 (memcmp(p_target_rec->ble.pseudo_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)
+ {
+ p_target_rec->ble.ble_addr_type = p_dev_rec->ble.ble_addr_type;
+ p_target_rec->device_type |= p_dev_rec->device_type;
+ p_dev_rec->sec_flags &= ~BTM_SEC_IN_USE;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
** Function btm_find_or_alloc_dev
**
** Description Look for the record in the device database for the record
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index ec0a03f..a8a1090 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -467,6 +467,7 @@
typedef struct
{
+ BD_ADDR pseudo_addr; /* LE pseudo address of the device if different from device address */
tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
tBLE_ADDR_TYPE static_addr_type; /* static address type */
BD_ADDR static_addr; /* static address */
@@ -585,6 +586,9 @@
** Link encrypted with such LK can be used
** for SM over BR/EDR.
*/
+ BOOLEAN no_smp_on_br; /* if set to TRUE then SMP on BR/EDR doesn't */
+ /* work, i.e. link keys crosspairing */
+ /* SC BR/EDR->SC LE doesn't happen */
#endif
// btla-specific ++
@@ -1004,10 +1008,10 @@
extern void btm_ble_add_2_white_list_complete(UINT8 status);
extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern BOOLEAN btm_ble_addr_resolvable(BD_ADDR rpa, tBTM_SEC_DEV_REC *p_dev_rec);
extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
extern BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
extern void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
#endif /* BLE_INCLUDED */
/* Vendor Specific Command complete evt handler */
@@ -1070,7 +1074,9 @@
extern void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC *p_dev_rec);
extern BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC **p_rec);
extern BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
+extern void btm_consolidate_dev(tBTM_SEC_DEV_REC *p_target_rec);
extern BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
+extern BOOLEAN btm_ble_init_pseudo_addr (tBTM_SEC_DEV_REC *p_dev_rec, BD_ADDR new_pseudo_addr);
#endif /* BLE_INCLUDED */
extern tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index c806782..33d0efc 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -995,6 +995,7 @@
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
if (transport == BT_TRANSPORT_LE)
{
+ btm_ble_init_pseudo_addr (p_dev_rec, bd_addr);
p_dev_rec->sec_flags &= ~ BTM_SEC_LE_MASK;
if (SMP_Pair(bd_addr) == SMP_STARTED)
@@ -4058,20 +4059,25 @@
else
{
BTM_TRACE_DEBUG ("TRYING TO DECIDE IF CAN USE SMP_BR_CHNL");
- if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec)))
+ if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec))
+ /* no LE keys are available, do deriving */
+ && (!(p_dev_rec->sec_flags &BTM_SEC_LE_LINK_KEY_KNOWN) ||
+ /* or BR key is higher security than existing LE keys */
+ (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED) &&
+ (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED))))
{
BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL");
if (btm_sec_is_master(p_dev_rec))
{
- // Encryption is required to start SM over BR/EDR.
- // Indicate that this is encryption after authentication.
+ // Encryption is required to start SM over BR/EDR
+ // indicate that this is encryption after authentication
BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL);
}
}
-
l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
}
+
return;
}
@@ -4150,7 +4156,8 @@
/* For transaction collision we need to wait and repeat. There is no need */
/* for random timeout because only slave should receive the result */
- if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) || (status == HCI_ERR_DIFF_TRANSACTION_COLLISION))
+ if ((status == HCI_ERR_LMP_ERR_TRANS_COLLISION) ||
+ (status == HCI_ERR_DIFF_TRANSACTION_COLLISION))
{
btm_sec_auth_collision(handle);
return;
@@ -4181,15 +4188,14 @@
BTM_TRACE_DEBUG ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
- if (acl_idx != MAX_L2CAP_LINKS )
+ if (acl_idx != MAX_L2CAP_LINKS)
p_acl = &btm_cb.acl_db[acl_idx];
btm_sec_check_pending_enc_req (p_dev_rec, p_acl->transport, encr_enable);
if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
{
- if (status == HCI_ERR_KEY_MISSING ||
- status == HCI_ERR_AUTH_FAILURE ||
+ if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE ||
status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
{
p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
@@ -4199,29 +4205,44 @@
return;
}
else
+ {
/* BR/EDR connection, update the encryption key size to be 16 as always */
p_dev_rec->enc_key_size = 16;
+ }
- BTM_TRACE_DEBUG ("in btm_sec_encrypt_change new_encr_key_256 is %d",
- p_dev_rec->new_encryption_key_is_p256);
+ BTM_TRACE_DEBUG ("in %s new_encr_key_256 is %d",
+ __func__, p_dev_rec->new_encryption_key_is_p256);
if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle))
{
if (p_dev_rec->new_encryption_key_is_p256)
{
if (btm_sec_use_smp_br_chnl(p_dev_rec) &&
- btm_sec_is_master(p_dev_rec))
+ btm_sec_is_master(p_dev_rec) &&
+ /* if LE key is not known, do deriving */
+ (!(p_dev_rec->sec_flags &BTM_SEC_LE_LINK_KEY_KNOWN) ||
+ /* or BR key is higher security than existing LE keys */
+ (!(p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+ && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_AUTHED))))
{
/* BR/EDR is encrypted with LK that can be used to derive LE LTK */
p_dev_rec->new_encryption_key_is_p256 = FALSE;
- BTM_TRACE_DEBUG ("btm_sec_encrypt_change start SM over BR/EDR");
- SMP_BR_PairWith(p_dev_rec->bd_addr);
+ if (p_dev_rec->no_smp_on_br)
+ {
+ BTM_TRACE_DEBUG ("%s NO SM over BR/EDR", __func__);
+ }
+ else
+ {
+ BTM_TRACE_DEBUG ("%s start SM over BR/EDR", __func__);
+ SMP_BR_PairWith(p_dev_rec->bd_addr);
+ }
}
}
else
- { /* BR/EDR is successfully encrypted. Correct LK type if needed
- (BR/EDR LK derived from LE LTK was used for encryption) */
+ {
+ // BR/EDR is successfully encrypted. Correct LK type if needed
+ // (BR/EDR LK derived from LE LTK was used for encryption)
if ((encr_enable == 1) && /* encryption is ON for SSP */
/* LK type is for BR/EDR SC */
(p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
@@ -4254,7 +4275,6 @@
}
p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
-
/* If encryption setup failed, notify the waiting layer */
if (status != HCI_SUCCESS)
{
@@ -4264,7 +4284,6 @@
/* Encryption setup succeeded, execute the next security procedure, if any */
status = (UINT8)btm_sec_execute_procedure (p_dev_rec);
-
/* If there is no next procedure, or procedure failed to start, notify the caller */
if (status != BTM_CMD_STARTED)
btm_sec_dev_rec_cback_event (p_dev_rec, status, FALSE);
@@ -4808,23 +4827,22 @@
p_link_key, p_dev_rec->link_key_type);
}
}
-#if BTM_CROSS_TRANSP_KEY_DERIVATION == TRUE
else
{
if ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) ||
(p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
{
- p_dev_rec->new_encr_key_256 = TRUE;
+ p_dev_rec->new_encryption_key_is_p256 = TRUE;
BTM_TRACE_DEBUG ("%s set new_encr_key_256 to %d",
- __func__, p_dev_rec->new_encr_key_256);
+ __func__, p_dev_rec->new_encryption_key_is_p256);
}
}
-#endif
/* If name is not known at this point delay calling callback until the name is */
/* resolved. Unless it is a HID Device and we really need to send all link keys. */
if ((!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
- && ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL)) )
+ && ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL))
+ && !ltk_derived_lk)
{
BTM_TRACE_EVENT ("btm_sec_link_key_notification() Delayed BDA: %08x%04x Type:%d",
(p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3],
@@ -4846,7 +4864,9 @@
/* If its not us who perform authentication, we should tell stackserver */
/* that some authentication has been completed */
/* This is required when different entities receive link notification and auth complete */
- if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE))
+ if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)
+ /* for derived key, always send authentication callback for BR channel */
+ || ltk_derived_lk)
{
if (btm_cb.api.p_auth_complete_callback)
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
@@ -4860,8 +4880,17 @@
{
if (btm_cb.api.p_link_key_callback)
{
- (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name,
- p_link_key, p_dev_rec->link_key_type);
+ if (ltk_derived_lk)
+ {
+ BTM_TRACE_DEBUG ("btm_sec_link_key_notification() LTK derived LK is saved already"
+ " (key_type = %d)", p_dev_rec->link_key_type);
+ }
+ else
+ {
+ (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
+ p_dev_rec->sec_bd_name,
+ p_link_key, p_dev_rec->link_key_type);
+ }
}
}
}
@@ -5839,12 +5868,15 @@
void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_transport)
{
tBTM_SEC_CALLBACK *p_callback = p_dev_rec->p_callback;
- tBT_TRANSPORT transport = is_le_transport ? BT_TRANSPORT_LE : BT_TRANSPORT_BR_EDR;
if (p_dev_rec->p_callback)
{
p_dev_rec->p_callback = NULL;
- (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, res);
+
+ if (is_le_transport)
+ (*p_callback) (p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE, p_dev_rec->p_ref_data, res);
+ else
+ (*p_callback) (p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, p_dev_rec->p_ref_data, res);
}
btm_sec_check_pending_reqs();
@@ -6214,11 +6246,8 @@
BOOLEAN le_capable = FALSE;
#if (BLE_INCLUDED== TRUE)
- if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) ||
- (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) )
- {
+ if (p_dev_rec && (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE)
le_capable = TRUE;
- }
#endif
return le_capable;
}
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index de0b195..a4d1ba3 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -1399,6 +1399,10 @@
#define BTM_AUTH_BONDS 6 /* the general/dedicated bonding bits */
#define BTM_AUTH_YN_BIT 1 /* this is the Yes or No bit */
+#define BTM_BLE_INITIATOR_KEY_SIZE 15
+#define BTM_BLE_RESPONDER_KEY_SIZE 15
+#define BTM_BLE_MAX_KEY_SIZE 16
+
typedef UINT8 tBTM_AUTH_REQ;
enum
@@ -1613,9 +1617,10 @@
/* data type for tBTM_LE_COMPLT */
typedef struct
{
- UINT8 reason;
- UINT8 sec_level;
- BOOLEAN is_pair_cancel;
+ UINT8 reason;
+ UINT8 sec_level;
+ BOOLEAN is_pair_cancel;
+ BOOLEAN smp_over_br;
}tBTM_LE_COMPLT;
#endif
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 37669b4..62ef1db 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -203,6 +203,14 @@
#define SMP_SEC_DEFAULT_KEY (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
SMP_SEC_KEY_TYPE_CSRK | SMP_SEC_KEY_TYPE_LK)
+#define SMP_SC_KEY_STARTED 0 /* passkey entry started */
+#define SMP_SC_KEY_ENTERED 1 /* passkey digit entered */
+#define SMP_SC_KEY_ERASED 2 /* passkey digit erased */
+#define SMP_SC_KEY_CLEARED 3 /* passkey cleared */
+#define SMP_SC_KEY_COMPLT 4 /* passkey entry completed */
+#define SMP_SC_KEY_OUT_OF_RANGE 5 /* out of range */
+typedef UINT8 tSMP_SC_KEY_TYPE;
+
/* data type for BTM_SP_IO_REQ_EVT */
typedef struct
{
@@ -216,9 +224,10 @@
typedef struct
{
- tSMP_STATUS reason;
- tSMP_SEC_LEVEL sec_level;
- BOOLEAN is_pair_cancel;
+ tSMP_STATUS reason;
+ tSMP_SEC_LEVEL sec_level;
+ BOOLEAN is_pair_cancel;
+ BOOLEAN smp_over_br;
} tSMP_CMPL;
typedef struct
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index fa2fcce..97bf58d 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -424,16 +424,21 @@
if (p_lcb->ccb_queue.p_first_ccb != NULL || p_lcb->p_pending_ccb)
{
L2CAP_TRACE_DEBUG("l2c_link_hci_disc_comp: Restarting pending ACL request");
+ transport = p_lcb->transport;
#if BLE_INCLUDED == TRUE
/* for LE link, always drop and re-open to ensure to get LE remote feature */
if (p_lcb->transport == BT_TRANSPORT_LE)
{
- BD_ADDR bd_addr;
- memcpy(bd_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
- l2cu_release_lcb (p_lcb);
- // make sure Tx credit allocation is redistributed in between links by calling l2cu_allocate_lcb
- p_lcb = l2cu_allocate_lcb (bd_addr, FALSE, BT_TRANSPORT_LE);
- transport = BT_TRANSPORT_LE;
+ l2cb.is_ble_connecting = FALSE;
+ btm_acl_removed (p_lcb->remote_bd_addr, p_lcb->transport);
+ /* Release any held buffers */
+ BT_HDR *p_buf;
+ while (!list_is_empty(p_lcb->link_xmit_data_q))
+ {
+ p_buf = list_front(p_lcb->link_xmit_data_q);
+ list_remove(p_lcb->link_xmit_data_q, p_buf);
+ GKI_freebuf(p_buf);
+ }
}
else
#endif
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 634f1cd..212d5df 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -186,6 +186,11 @@
STREAM_TO_UINT16 (l2cap_len, p);
STREAM_TO_UINT16 (rcv_cid, p);
+ /* for BLE channel, always notify connection when ACL data received on the link */
+ if (p_lcb && p_lcb->transport == BT_TRANSPORT_LE && p_lcb->link_state != LST_DISCONNECTING)
+ /* only process fixed channel data as channel open indication when link is not in disconnecting mode */
+ l2cble_notify_le_connection(p_lcb->remote_bd_addr);
+
/* Find the CCB for this CID */
if (rcv_cid >= L2CAP_BASE_APPL_CID)
{
@@ -261,14 +266,10 @@
counter_add("l2cap.fix.rx.pkts", 1);
/* If no CCB for this channel, allocate one */
if (p_lcb &&
- /* discard fixed channel data when link is disconnecting */
+ /* only process fixed channel data when link is open or wait for data indication */
(p_lcb->link_state != LST_DISCONNECTING) &&
- l2cu_initialize_fixed_ccb (p_lcb, rcv_cid,
- &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
+ l2cu_initialize_fixed_ccb (p_lcb, rcv_cid, &l2cb.fixed_reg[rcv_cid - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
{
-#if(defined BLE_INCLUDED && (BLE_INCLUDED == TRUE))
- l2cble_notify_le_connection(p_lcb->remote_bd_addr);
-#endif
p_ccb = p_lcb->p_fixed_ccbs[rcv_cid - L2CAP_FIRST_FIXED_CHNL];
if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE)
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index 397a2ca..f1c6936 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -46,7 +46,7 @@
smp_generate_ltk,
smp_send_id_info,
smp_generate_csrk,
- smp_derive_link_key_from_long_term_key
+ smp_set_derive_link_key
};
/*******************************************************************************
@@ -58,7 +58,8 @@
SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x",
__func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key);
- if (((p_cb->le_secure_connections_mode_is_used) || (p_cb->smp_over_br)) &&
+ if (((p_cb->le_secure_connections_mode_is_used) ||
+ (p_cb->smp_over_br)) &&
((key_type == SMP_SEC_KEY_TYPE_ENC) || (key_type == SMP_SEC_KEY_TYPE_LK)))
{
/* in LE SC mode LTK, CSRK and BR/EDR LK are derived locally instead of
@@ -176,11 +177,9 @@
p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
}
-#if BTM_CROSS_TRANSP_KEY_DERIVATION == FALSE
SMP_TRACE_WARNING ("Cross transport key derivation is not supported");
p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
-#endif
SMP_TRACE_WARNING("set auth_req: 0x%02x, local_i_key: 0x%02x, local_r_key: 0x%02x",
p_cb->loc_auth_req, p_cb->local_i_key, p_cb->local_r_key);
@@ -986,6 +985,11 @@
STREAM_TO_BDADDR(pid_key.static_addr, p);
memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+ /* to use as BD_ADDR for lk derived from ltk */
+ p_cb->id_addr_rcvd = TRUE;
+ p_cb->id_addr_type = pid_key.addr_type;
+ memcpy(p_cb->id_addr, pid_key.static_addr, BD_ADDR_LEN);
+
/* store the ID key from peer device */
if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
@@ -1217,8 +1221,8 @@
SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
__func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
- if (p_cb->role == HCI_ROLE_SLAVE||
- (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+ if (p_cb->role == HCI_ROLE_SLAVE ||
+ (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
{
smp_key_pick_key(p_cb, p_data);
}
@@ -1228,6 +1232,12 @@
/* state check to prevent re-entrant */
if (smp_get_state() == SMP_STATE_BOND_PENDING)
{
+ if (p_cb->derive_lk)
+ {
+ smp_derive_link_key_from_long_term_key(p_cb, NULL);
+ p_cb->derive_lk = FALSE;
+ }
+
if (p_cb->total_tx_unacked == 0)
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
else
@@ -1976,6 +1986,25 @@
/*******************************************************************************
**
+** Function smp_set_derive_link_key
+**
+** Description This function is called to set flag that indicates that
+** BR/EDR LK has to be derived from LTK after all keys are
+** distributed.
+**
+** Returns void
+**
+*******************************************************************************/
+void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+ SMP_TRACE_DEBUG ("%s", __func__);
+ p_cb->derive_lk = TRUE;
+ smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
+ smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
** Function smp_derive_link_key_from_long_term_key
**
** Description This function is called to derive BR/EDR LK from LTK.
@@ -1996,7 +2025,6 @@
}
smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
-
SMP_TRACE_DEBUG("%s successfully completed", __FUNCTION__);
smp_key_distribution(p_cb, NULL);
}
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 24aa3ec..52b0301 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -270,6 +270,10 @@
UINT8 trace_level;
BD_ADDR pairing_bda;
tSMP_STATE state;
+ BOOLEAN derive_lk;
+ BOOLEAN id_addr_rcvd;
+ tBLE_ADDR_TYPE id_addr_type;
+ BD_ADDR id_addr;
BOOLEAN smp_over_br;
tSMP_BR_STATE br_state; /* if SMP over BR/ERD has priority over SMP */
UINT8 failure;
@@ -305,8 +309,9 @@
/* either in Secure Connections mode or not at all */
tSMP_ASSO_MODEL selected_association_model;
BOOLEAN le_secure_connections_mode_is_used;
- tBTM_SP_KEY_TYPE local_keypress_notification;
- tBTM_SP_KEY_TYPE peer_keypress_notification;
+ BOOLEAN le_sc_kp_notif_is_used;
+ tSMP_SC_KEY_TYPE local_keypress_notification;
+ tSMP_SC_KEY_TYPE peer_keypress_notification;
UINT8 round; /* authentication stage 1 round for passkey association model */
UINT32 number_to_display;
BT_OCTET16 mac_key;
@@ -447,9 +452,10 @@
extern void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_process_secure_connection_long_term_key(void);
-extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_derive_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
extern void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index 47d0125..f301530 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -1926,9 +1926,27 @@
BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb)
{
tBTM_SEC_DEV_REC *p_dev_rec;
+ BD_ADDR bda_for_lk;
+ tBLE_ADDR_TYPE conn_addr_type;
SMP_TRACE_DEBUG ("%s", __func__);
+ if (p_cb->id_addr_rcvd && p_cb->id_addr_type == BLE_ADDR_PUBLIC)
+ {
+ SMP_TRACE_DEBUG ("Use rcvd identity address as BD_ADDR of LK rcvd identity address");
+ memcpy(bda_for_lk, p_cb->id_addr, BD_ADDR_LEN);
+ }
+ else if ((BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, bda_for_lk, &conn_addr_type)) &&
+ conn_addr_type == BLE_ADDR_PUBLIC)
+ {
+ SMP_TRACE_DEBUG ("Use rcvd connection address as BD_ADDR of LK");
+ }
+ else
+ {
+ SMP_TRACE_WARNING ("Don't have peer public address to associate with LK");
+ return FALSE;
+ }
+
if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
{
SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
@@ -1989,7 +2007,7 @@
p = notif_link_key;
ARRAY16_TO_STREAM(p, link_key);
- btm_sec_link_key_notification (p_cb->pairing_bda, notif_link_key, link_key_type);
+ btm_sec_link_key_notification (bda_for_lk, notif_link_key, link_key_type);
SMP_TRACE_EVENT ("%s is completed", __func__);
}
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 9f2e532..3e592f2 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -942,6 +942,7 @@
SMP_TRACE_DEBUG ("smp_proc_pairing_cmpl ");
evt_data.cmplt.reason = p_cb->status;
+ evt_data.cmplt.smp_over_br = p_cb->smp_over_br;
if (p_cb->status == SMP_SUCCESS)
evt_data.cmplt.sec_level = p_cb->sec_level;