|
|
@@ -2603,6 +2603,64 @@ unlock:
|
|
|
hci_dev_unlock(hdev);
|
|
|
}
|
|
|
|
|
|
+static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
|
|
|
+ u16 opcode, struct sk_buff *skb)
|
|
|
+{
|
|
|
+ const struct hci_rp_read_enc_key_size *rp;
|
|
|
+ struct hci_conn *conn;
|
|
|
+ u16 handle;
|
|
|
+
|
|
|
+ BT_DBG("%s status 0x%02x", hdev->name, status);
|
|
|
+
|
|
|
+ if (!skb || skb->len < sizeof(*rp)) {
|
|
|
+ BT_ERR("%s invalid HCI Read Encryption Key Size response",
|
|
|
+ hdev->name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ rp = (void *)skb->data;
|
|
|
+ handle = le16_to_cpu(rp->handle);
|
|
|
+
|
|
|
+ hci_dev_lock(hdev);
|
|
|
+
|
|
|
+ conn = hci_conn_hash_lookup_handle(hdev, handle);
|
|
|
+ if (!conn)
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
+ /* If we fail to read the encryption key size, assume maximum
|
|
|
+ * (which is the same we do also when this HCI command isn't
|
|
|
+ * supported.
|
|
|
+ */
|
|
|
+ if (rp->status) {
|
|
|
+ BT_ERR("%s failed to read key size for handle %u", hdev->name,
|
|
|
+ handle);
|
|
|
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
|
|
|
+ } else {
|
|
|
+ conn->enc_key_size = rp->key_size;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (conn->state == BT_CONFIG) {
|
|
|
+ conn->state = BT_CONNECTED;
|
|
|
+ hci_connect_cfm(conn, 0);
|
|
|
+ hci_conn_drop(conn);
|
|
|
+ } else {
|
|
|
+ u8 encrypt;
|
|
|
+
|
|
|
+ if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags))
|
|
|
+ encrypt = 0x00;
|
|
|
+ else if (conn->type == ACL_LINK &&
|
|
|
+ test_bit(HCI_CONN_AES_CCM, &conn->flags))
|
|
|
+ encrypt = 0x02;
|
|
|
+ else
|
|
|
+ encrypt = 0x01;
|
|
|
+
|
|
|
+ hci_encrypt_cfm(conn, 0, encrypt);
|
|
|
+ }
|
|
|
+
|
|
|
+unlock:
|
|
|
+ hci_dev_unlock(hdev);
|
|
|
+}
|
|
|
+
|
|
|
static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
{
|
|
|
struct hci_ev_encrypt_change *ev = (void *) skb->data;
|
|
|
@@ -2662,6 +2720,35 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
goto unlock;
|
|
|
}
|
|
|
|
|
|
+ /* Try reading the encryption key size for encrypted ACL links */
|
|
|
+ if (!ev->status && ev->encrypt && conn->type == ACL_LINK) {
|
|
|
+ struct hci_cp_read_enc_key_size cp;
|
|
|
+ struct hci_request req;
|
|
|
+
|
|
|
+ /* Only send HCI_Read_Encryption_Key_Size if the
|
|
|
+ * controller really supports it. If it doesn't, assume
|
|
|
+ * the default size (16).
|
|
|
+ */
|
|
|
+ if (!(hdev->commands[20] & 0x10)) {
|
|
|
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
|
|
|
+ goto notify;
|
|
|
+ }
|
|
|
+
|
|
|
+ hci_req_init(&req, hdev);
|
|
|
+
|
|
|
+ cp.handle = cpu_to_le16(conn->handle);
|
|
|
+ hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
|
|
|
+
|
|
|
+ if (hci_req_run_skb(&req, read_enc_key_size_complete)) {
|
|
|
+ BT_ERR("Sending HCI Read Encryption Key Size failed");
|
|
|
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
|
|
|
+ goto notify;
|
|
|
+ }
|
|
|
+
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+notify:
|
|
|
if (conn->state == BT_CONFIG) {
|
|
|
if (!ev->status)
|
|
|
conn->state = BT_CONNECTED;
|