Skip to content
Permalink
Browse files

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>
  • Loading branch information...
jhedberg committed Jul 31, 2018
1 parent da8f62d commit ef70fc85a99918909b5b5e834343d8daa59e963f
Showing with 18 additions and 13 deletions.
  1. +18 −13 subsys/bluetooth/host/smp.c
@@ -2311,6 +2311,10 @@ int bt_smp_send_security_req(struct bt_conn *conn)
return -EINVAL;
}

if (smp_init(smp) != 0) {
return -ENOBUFS;
}

req_buf = smp_create_pdu(conn, BT_SMP_CMD_SECURITY_REQUEST,
sizeof(*req));
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 */
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;
}
@@ -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 *rsp;
int ret;

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;
}

ret = smp_init(smp);
if (ret) {
return ret;
/* If we already sent a security request then the SMP context
* is already initialized.
*/
if (!atomic_test_bit(smp->flags, SMP_FLAG_SEC_REQ)) {
int ret = smp_init(smp);

if (ret) {
return ret;
}
}

/* Store req for later use */
@@ -3584,22 +3594,17 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
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.
* This can happen if paired slave sent Security Request and we
* 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)) {
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
smp_reset(smp);
return;
}

atomic_clear_bit(smp->flags, SMP_FLAG_ENC_PENDING);

/* derive BR/EDR LinkKey if supported by both sides */
if (atomic_test_bit(smp->flags, SMP_FLAG_SC)) {
if ((smp->local_dist & BT_SMP_DIST_LINK_KEY) &&

0 comments on commit ef70fc8

Please sign in to comment.
You can’t perform that action at this time.