diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 037f923b433b923625246f6603493a967568ea3f..90e076013bad6ae06ba9930e910a3dc065a95a56 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3053,6 +3053,7 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, const struct hci_rp_read_enc_key_size *rp; struct hci_conn *conn; u16 handle; + u8 st; BT_DBG("%s status 0x%02x", hdev->name, status); @@ -3062,6 +3063,7 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, } rp = (void *)skb->data; + st = rp->status; handle = le16_to_cpu(rp->handle); hci_dev_lock(hdev); @@ -3074,15 +3076,30 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, * secure approach is to then assume the key size is 0 to force a * disconnection. */ - if (rp->status) { + if (st) { bt_dev_err(hdev, "failed to read key size for handle %u", handle); conn->enc_key_size = 0; } else { conn->enc_key_size = rp->key_size; + st = 0; + + if (conn->enc_key_size < hdev->min_enc_key_size) { + /* As slave role, the conn->state has been set to + * BT_CONNECTED and l2cap conn req might not be received + * yet, at this moment the l2cap layer almost does + * nothing with the non-zero status. + * So we also clear encrypt related bits, and then the + * handler of l2cap conn req will get the right secure + * state at a later time. + */ + st = HCI_ERROR_AUTH_FAILURE; + clear_bit(HCI_CONN_ENCRYPT, &conn->flags); + clear_bit(HCI_CONN_AES_CCM, &conn->flags); + } } - hci_encrypt_cfm(conn, 0); + hci_encrypt_cfm(conn, st); unlock: hci_dev_unlock(hdev);