fix(ble/bluedroid): fix L2CAP, SMP and HCI command issues

- Fix active_count check in l2cu_ble_plcb_active_count
- Restore previous state if connection command fails
- Fix HCI cmd buffer size off-by-one errors
- Fix connect handle length errors
- Fix channel sounding event status handling
- Fix SMP param_len check in smp_rand_back
- Fix spelling: BROCASTER to BROADCASTER in definitions
This commit is contained in:
zhiweijian
2026-02-27 17:59:59 +08:00
parent e0ccc644a8
commit e118d053b3
13 changed files with 183 additions and 65 deletions
@@ -177,9 +177,16 @@ static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength
k[0] = k[0] + 1;
if (k[0] == 0) { //overflow
j = 1;
do {
while (j < keyLength && k[j] == 0xFFFFFFFF) {
k[j] = 0;
j++;
}
if (j < keyLength) {
k[j]++;
} while (k[j++] == 0); //overflow
}
// If j >= keyLength, the entire key is 0xFFFFFFFF,
// which should not happen for a valid private key.
// In this case, we stop the propagation to prevent buffer overflow.
}
}
} else {
@@ -621,10 +621,10 @@ void smp_concatenate_peer( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code)
** Description Generate Confirm/Compare Step1:
** p1 = press || preq || rat' || iat'
**
** Returns void
** Returns BOOLEAN
**
*******************************************************************************/
void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
BOOLEAN smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
{
UINT8 *p = (UINT8 *)p1;
tBLE_ADDR_TYPE addr_type = 0;
@@ -634,7 +634,7 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type)) {
SMP_TRACE_ERROR("can not generate confirm for unknown device\n");
return;
return FALSE;
}
BTM_ReadConnectionAddr( p_cb->pairing_bda, p_cb->local_bda, &p_cb->addr_type);
@@ -662,6 +662,7 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
SMP_TRACE_DEBUG("p1 = press || preq || rat' || iat'\n");
smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1", 16);
#endif
return TRUE;
}
/*******************************************************************************
@@ -725,7 +726,11 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda)
SMP_TRACE_DEBUG ("smp_calculate_comfirm \n");
/* generate p1 = press || preq || rat' || iat' */
smp_gen_p1_4_confirm(p_cb, p1);
if (!smp_gen_p1_4_confirm(p_cb, p1)) {
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
return ;
}
/* p1 = rand XOR p1 */
smp_xor_128(p1, rand);
@@ -1138,6 +1143,12 @@ void smp_continue_private_key_creation (tSMP_CB *p_cb, tBTM_RAND_ENC *p)
UINT8 state = p_cb->rand_enc_proc_state & ~0x80;
SMP_TRACE_DEBUG ("%s state=0x%x\n", __func__, state);
/* Validate param_len to prevent buffer overflow/underflow */
if (p == NULL || p->param_len != BT_OCTET8_LEN) {
SMP_TRACE_ERROR("invalid param_len: %d, expected %d\n", p ? p->param_len : 0, BT_OCTET8_LEN);
return;
}
switch (state) {
case SMP_GENERATE_PRIVATE_KEY_0_7:
memcpy((void *)p_cb->private_key, p->param_buf, p->param_len);
@@ -1543,6 +1554,9 @@ void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf)
**
** Note The LSB is the first octet, the MSB is the last octet of
** the AES-CMAC input/output stream.
** In little-endian implementation, the message is constructed
** as Z||V||U (reversed parameter order) to compensate for
** byte order differences with the big-endian specification.
**
*******************************************************************************/
void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c)
@@ -2041,11 +2055,16 @@ BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t)
*******************************************************************************/
void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 iocap[3], a[7], b[7];
UINT8 iocap[3], a[7] = {0}, b[7] = {0};
SMP_TRACE_DEBUG ("%s", __FUNCTION__);
smp_calculate_f5_mackey_and_long_term_key(p_cb);
if (!smp_calculate_f5_mackey_and_long_term_key(p_cb)) {
UINT8 reason = SMP_PAIR_FAIL_UNKNOWN;
p_cb->failure = reason;
smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
return;
}
smp_collect_local_io_capabilities(iocap, p_cb);
@@ -2068,7 +2087,7 @@ void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
*******************************************************************************/
void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
{
UINT8 iocap[3], a[7], b[7];
UINT8 iocap[3], a[7] = {0}, b[7] = {0};
BT_OCTET16 param_buf;
BOOLEAN ret;
tSMP_KEY key;
@@ -2482,37 +2501,62 @@ static void smp_rand_back(tBTM_RAND_ENC *p)
UINT8 *pp = NULL;
UINT8 failure = SMP_PAIR_FAIL_UNKNOWN;
UINT8 state = p_cb->rand_enc_proc_state & ~0x80;
BOOLEAN check_failed = FALSE;
SMP_TRACE_DEBUG ("%s state=0x%x", __FUNCTION__, state);
if (p && p->status == HCI_SUCCESS) {
switch (state) {
case SMP_GEN_SRAND_MRAND:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
smp_generate_rand_cont(p_cb, NULL);
break;
case SMP_GEN_SRAND_MRAND_CONT:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
smp_generate_confirm(p_cb, NULL);
break;
case SMP_GEN_DIV_LTK:
if (p->param_len < 2) {
check_failed = TRUE;
break;
}
pp = p->param_buf;
STREAM_TO_UINT16(p_cb->div, pp);
smp_generate_ltk_cont(p_cb, NULL);
break;
case SMP_GEN_DIV_CSRK:
if (p->param_len < 2) {
check_failed = TRUE;
break;
}
pp = p->param_buf;
STREAM_TO_UINT16(p_cb->div, pp);
smp_compute_csrk(p_cb, NULL);
break;
case SMP_GEN_TK:
if (p->param_len < 4) {
check_failed = TRUE;
break;
}
smp_proc_passkey(p_cb, p);
break;
case SMP_GEN_RAND_V:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
smp_generate_y(p_cb, NULL);
break;
@@ -2521,21 +2565,34 @@ static void smp_rand_back(tBTM_RAND_ENC *p)
case SMP_GENERATE_PRIVATE_KEY_8_15:
case SMP_GENERATE_PRIVATE_KEY_16_23:
case SMP_GENERATE_PRIVATE_KEY_24_31:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
smp_continue_private_key_creation(p_cb, p);
break;
case SMP_GEN_NONCE_0_7:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
smp_finish_nonce_generation(p_cb);
break;
case SMP_GEN_NONCE_8_15:
if (p->param_len != BT_OCTET8_LEN) {
check_failed = TRUE;
break;
}
memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
smp_process_new_nonce(p_cb);
break;
}
return;
if (!check_failed) {
return;
}
}
SMP_TRACE_ERROR("%s key generation failed: (%d)", __FUNCTION__, p_cb->rand_enc_proc_state);
@@ -749,11 +749,14 @@ static BT_HDR *smp_build_pairing_commitment_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
UINT8 *p;
UNUSED(cmd_code);
SMP_TRACE_EVENT("%s\n", __func__);
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR) + SMP_PAIR_COMMITM_SIZE + L2CAP_MIN_OFFSET))
!= NULL) {
p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
/* The transmitter sends 0x03 universally.
The receiver performs automatic conversion according to its capabilities to ensure backward compatibility.
The state machine operates using the translated opcode. please refer to smp_data_received() in smp_l2c.c
Please note that using SMP OPCODE to CONFIRM is not an error.
*/
UINT8_TO_STREAM (p, SMP_OPCODE_CONFIRM);
ARRAY_TO_STREAM (p, p_cb->commitment, BT_OCTET16_LEN);
@@ -1462,7 +1465,7 @@ void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb)
void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
{
tBLE_ADDR_TYPE addr_type = 0;
BD_ADDR bda;
BD_ADDR bda = {0};
UINT8 *p = le_addr;
SMP_TRACE_DEBUG("%s\n", __func__);
@@ -1485,7 +1488,7 @@ void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
{
tBLE_ADDR_TYPE addr_type = 0;
BD_ADDR bda;
BD_ADDR bda = {0};
UINT8 *p = le_addr;
SMP_TRACE_DEBUG("%s\n", __func__);
@@ -1574,8 +1577,8 @@ void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb)
*******************************************************************************/
BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb)
{
UINT8 a[7];
UINT8 b[7];
UINT8 a[7] = {0};
UINT8 b[7] = {0};
UINT8 *p_na;
UINT8 *p_nb;