Bluetooth: SMP: Handle both devices initiating security
Handle case where: - Peripheral sends security request after master has sent pairing request or started encryption procedure. This packet can be ignored, as long as the slave has not already responded with pairing response. - Central wants to start security after peripheral initiated security request, return error code busy in this case Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
eb6ae10745
commit
2ac5841928
2 changed files with 59 additions and 7 deletions
|
@ -327,6 +327,9 @@ typedef enum __packed {
|
|||
* to achieve due to local or remote device limitation (e.g., input output
|
||||
* capabilities), or if the maximum number of paired devices has been reached.
|
||||
*
|
||||
* This function may return error if the pairing procedure has already been
|
||||
* initiated by the local device or the peer device.
|
||||
*
|
||||
* @param conn Connection object.
|
||||
* @param sec Requested security level.
|
||||
*
|
||||
|
|
|
@ -2585,6 +2585,7 @@ bool bt_smp_request_ltk(struct bt_conn *conn, u64_t rand, u16_t ediv, u8_t *ltk)
|
|||
BT_SMP_MAX_ENC_KEY_SIZE - enc_size);
|
||||
}
|
||||
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2622,6 +2623,7 @@ bool bt_smp_request_ltk(struct bt_conn *conn, u64_t rand, u16_t ediv, u8_t *ltk)
|
|||
BT_SMP_MAX_ENC_KEY_SIZE - enc_size);
|
||||
}
|
||||
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
return true;
|
||||
}
|
||||
#endif /* !CONFIG_BT_SMP_SC_PAIR_ONLY */
|
||||
|
@ -2662,6 +2664,10 @@ static int smp_send_security_req(struct bt_conn *conn)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* early verify if required sec level if reachable */
|
||||
if (!(sec_level_reachable(conn) || smp_keys_check(conn))) {
|
||||
return -EINVAL;
|
||||
|
@ -2858,6 +2864,11 @@ static int smp_send_pairing_req(struct bt_conn *conn)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Encryption is in progress */
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* early verify if required sec level if reachable */
|
||||
if (!sec_level_reachable(conn)) {
|
||||
return -EINVAL;
|
||||
|
@ -2899,6 +2910,7 @@ static int smp_send_pairing_req(struct bt_conn *conn)
|
|||
smp_send(smp, req_buf, NULL, NULL);
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PAIRING_RSP);
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_PAIRING);
|
||||
|
||||
return 0;
|
||||
|
@ -2982,6 +2994,8 @@ static u8_t smp_pairing_rsp(struct bt_smp *smp, struct net_buf *buf)
|
|||
}
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_PUBLIC_KEY);
|
||||
atomic_clear_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
|
||||
|
||||
return sc_send_public_key(smp);
|
||||
}
|
||||
#else
|
||||
|
@ -3650,6 +3664,16 @@ static u8_t smp_security_request(struct bt_smp *smp, struct net_buf *buf)
|
|||
|
||||
BT_DBG("");
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
|
||||
/* We have already started pairing process */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
|
||||
/* We have already started encryption procedure */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sc_supported) {
|
||||
auth = req->auth_req & BT_SMP_AUTH_MASK_SC;
|
||||
} else {
|
||||
|
@ -4137,6 +4161,8 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
|
|||
BT_DBG("chan %p conn %p handle %u encrypt 0x%02x hci status 0x%02x",
|
||||
chan, conn, conn->handle, conn->encrypt, hci_status);
|
||||
|
||||
atomic_clear_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
|
||||
if (hci_status) {
|
||||
return;
|
||||
}
|
||||
|
@ -4154,8 +4180,6 @@ static void bt_smp_encrypt_change(struct bt_l2cap_chan *chan,
|
|||
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) &&
|
||||
|
@ -5074,16 +5098,41 @@ int bt_smp_start_security(struct bt_conn *conn)
|
|||
#if defined(CONFIG_BT_CENTRAL)
|
||||
case BT_HCI_ROLE_MASTER:
|
||||
{
|
||||
int err;
|
||||
struct bt_smp *smp;
|
||||
|
||||
smp = smp_chan_get(conn);
|
||||
if (!smp) {
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (!smp_keys_check(conn)) {
|
||||
return smp_send_pairing_req(conn);
|
||||
}
|
||||
|
||||
/* pairing is in progress */
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_PAIRING)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Encryption is in progress */
|
||||
if (atomic_test_bit(smp->flags, SMP_FLAG_ENC_PENDING)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* LE SC LTK and legacy master LTK are stored in same place */
|
||||
return bt_conn_le_start_encryption(conn,
|
||||
conn->le.keys->ltk.rand,
|
||||
conn->le.keys->ltk.ediv,
|
||||
conn->le.keys->ltk.val,
|
||||
conn->le.keys->enc_size);
|
||||
err = bt_conn_le_start_encryption(conn,
|
||||
conn->le.keys->ltk.rand,
|
||||
conn->le.keys->ltk.ediv,
|
||||
conn->le.keys->ltk.val,
|
||||
conn->le.keys->enc_size);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_set_bit(&smp->allowed_cmds, BT_SMP_CMD_SECURITY_REQUEST);
|
||||
atomic_set_bit(smp->flags, SMP_FLAG_ENC_PENDING);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_SMP */
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue