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:
Johan Hedberg 2018-07-31 13:28:51 +03:00 committed by Johan Hedberg
commit ef70fc85a9

View file

@ -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) &&