Bluetooth: SMP: Fix SMP context init when sending security request
The code was not doing the right thing when we as peripheral would send a security request to the central. First of all, the SEQ_REQ flag was getting cleared by the pairing request handler, resulting in pairing_confirm() callbacks for no reason. Secondly, the behavior in encrypt_change() was not utilizing the smp_reset() helper as it should have done. Fix the situation by calling smp_init() when sending a security request, and detect that this has been done when receiving a pairing request. Also do the appropriate cleanup if the result is an encrypt change instead of a pairing request (in case we were already paired with the peer). Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
da8f62de3a
commit
ef70fc85a9
1 changed files with 18 additions and 13 deletions
|
@ -2311,6 +2311,10 @@ int bt_smp_send_security_req(struct bt_conn *conn)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (smp_init(smp) != 0) {
|
||||||
|
return -ENOBUFS;
|
||||||
|
}
|
||||||
|
|
||||||
req_buf = smp_create_pdu(conn, BT_SMP_CMD_SECURITY_REQUEST,
|
req_buf = smp_create_pdu(conn, BT_SMP_CMD_SECURITY_REQUEST,
|
||||||
sizeof(*req));
|
sizeof(*req));
|
||||||
if (!req_buf) {
|
if (!req_buf) {
|
||||||
|
@ -2323,7 +2327,8 @@ int bt_smp_send_security_req(struct bt_conn *conn)
|
||||||
/* SMP timer is not restarted for SecRequest so don't use smp_send */
|
/* SMP timer is not restarted for SecRequest so don't use smp_send */
|
||||||
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, req_buf);
|
bt_l2cap_send(conn, BT_L2CAP_CID_SMP, req_buf);
|
||||||
|
|
||||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_FAIL);
|
atomic_set_bit(smp->flags, SMP_FLAG_SEC_REQ);
|
||||||
|
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_REQ);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2332,7 +2337,6 @@ static u8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
|
||||||
{
|
{
|
||||||
struct bt_smp_pairing *req = (void *)buf->data;
|
struct bt_smp_pairing *req = (void *)buf->data;
|
||||||
struct bt_smp_pairing *rsp;
|
struct bt_smp_pairing *rsp;
|
||||||
int ret;
|
|
||||||
|
|
||||||
BT_DBG("");
|
BT_DBG("");
|
||||||
|
|
||||||
|
@ -2341,9 +2345,15 @@ static u8_t smp_pairing_req(struct bt_smp *smp, struct net_buf *buf)
|
||||||
return BT_SMP_ERR_ENC_KEY_SIZE;
|
return BT_SMP_ERR_ENC_KEY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = smp_init(smp);
|
/* If we already sent a security request then the SMP context
|
||||||
if (ret) {
|
* is already initialized.
|
||||||
return ret;
|
*/
|
||||||
|
if (!atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) {
|
||||||
|
int ret = smp_init(smp);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store req for later use */
|
/* Store req for later use */
|
||||||
|
@ -3584,22 +3594,17 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!atomic_test_and_clear_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We were waiting for encryption but with no pairing in progress.
|
/* We were waiting for encryption but with no pairing in progress.
|
||||||
* This can happen if paired slave sent Security Request and we
|
* This can happen if paired slave sent Security Request and we
|
||||||
* enabled encryption.
|
* enabled encryption.
|
||||||
*
|
|
||||||
* Since it is possible that slave might sent another Security Request
|
|
||||||
* eg with different AuthReq we should allow it.
|
|
||||||
*/
|
*/
|
||||||
if (!atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
|
if (!atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
|
||||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
|
smp_reset(smp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_clear_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||||
|
|
||||||
/* derive BR/EDR LinkKey if supported by both sides */
|
/* derive BR/EDR LinkKey if supported by both sides */
|
||||||
if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
|
if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
|
||||||
if ((smp->local_dist & BT_SMP_DIST_LINK_KEY) &&
|
if ((smp->local_dist & BT_SMP_DIST_LINK_KEY) &&
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue