]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/bluetooth/hci_event.c
Bluetooth: Add hci_conn flag for new link key generation
[mirror_ubuntu-bionic-kernel.git] / net / bluetooth / hci_event.c
index a6000823f0ff34d938631bed2e39a6b17a26ac13..c3d6390e3b7b6ae546a6eae6797f0f4f0543841b 100644 (file)
@@ -189,6 +189,9 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
 
        clear_bit(HCI_RESET, &hdev->flags);
 
+       if (status)
+               return;
+
        /* Reset all non-persistent flags */
        hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
@@ -205,6 +208,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
        hdev->le_scan_type = LE_SCAN_PASSIVE;
 
        hdev->ssp_debug_mode = 0;
+
+       hci_bdaddr_list_clear(&hdev->le_white_list);
 }
 
 static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -989,8 +994,8 @@ static void hci_cc_read_local_oob_data(struct hci_dev *hdev,
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
        hci_dev_lock(hdev);
-       mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
-                                         NULL, NULL, rp->status);
+       mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->rand, NULL, NULL,
+                                         rp->status);
        hci_dev_unlock(hdev);
 }
 
@@ -1002,8 +1007,8 @@ static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev,
        BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
 
        hci_dev_lock(hdev);
-       mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
-                                         rp->hash256, rp->randomizer256,
+       mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->rand192,
+                                         rp->hash256, rp->rand256,
                                          rp->status);
        hci_dev_unlock(hdev);
 }
@@ -1045,7 +1050,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_dev_lock(hdev);
 
-       /* If we're doing connection initation as peripheral. Set a
+       /* If we're doing connection initiation as peripheral. Set a
         * timeout in case something goes wrong.
         */
        if (*sent) {
@@ -1576,9 +1581,15 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
        struct discovery_state *discov = &hdev->discovery;
        struct inquiry_entry *e;
 
-       if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-               mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
-                                     name_len, conn->dev_class);
+       /* Update the mgmt connected state if necessary. Be careful with
+        * conn objects that exist but are not (yet) connected however.
+        * Only those in BT_CONFIG or BT_CONNECTED states can be
+        * considered connected.
+        */
+       if (conn &&
+           (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
+           !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+               mgmt_device_connected(hdev, conn, 0, name, name_len);
 
        if (discov->state == DISCOVERY_STOPPED)
                return;
@@ -1943,6 +1954,29 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
+{
+       struct hci_cp_switch_role *cp;
+       struct hci_conn *conn;
+
+       BT_DBG("%s status 0x%2.2x", hdev->name, status);
+
+       if (!status)
+               return;
+
+       cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
+       if (!cp)
+               return;
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+       if (conn)
+               clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
+
+       hci_dev_unlock(hdev);
+}
+
 static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -2071,6 +2105,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        cp.handle = ev->handle;
                        hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
                                     sizeof(cp), &cp);
+
+                       hci_update_page_scan(hdev, NULL);
                }
 
                /* Set packet type for incoming connection */
@@ -2247,9 +2283,12 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
                                reason, mgmt_connected);
 
-       if (conn->type == ACL_LINK &&
-           test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
-               hci_remove_link_key(hdev, &conn->dst);
+       if (conn->type == ACL_LINK) {
+               if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
+                       hci_remove_link_key(hdev, &conn->dst);
+
+               hci_update_page_scan(hdev, NULL);
+       }
 
        params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
        if (params) {
@@ -2315,8 +2354,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        conn->sec_level = conn->pending_sec_level;
                }
        } else {
-               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-                                ev->status);
+               mgmt_auth_failed(conn, ev->status);
        }
 
        clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
@@ -2434,6 +2472,12 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
                }
        }
 
+       /* We should disregard the current RPA and generate a new one
+        * whenever the encryption procedure fails.
+        */
+       if (ev->status && conn->type == LE_LINK)
+               set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
+
        clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
 
        if (ev->status && conn->state == BT_CONNECTED) {
@@ -2526,9 +2570,7 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
        } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-               mgmt_device_connected(hdev, &conn->dst, conn->type,
-                                     conn->dst_type, 0, NULL, 0,
-                                     conn->dev_class);
+               mgmt_device_connected(hdev, conn, 0, NULL, 0);
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -2838,6 +2880,10 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cs_create_conn(hdev, ev->status);
                break;
 
+       case HCI_OP_DISCONNECT:
+               hci_cs_disconnect(hdev, ev->status);
+               break;
+
        case HCI_OP_ADD_SCO:
                hci_cs_add_sco(hdev, ev->status);
                break;
@@ -2866,24 +2912,24 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cs_setup_sync_conn(hdev, ev->status);
                break;
 
-       case HCI_OP_SNIFF_MODE:
-               hci_cs_sniff_mode(hdev, ev->status);
+       case HCI_OP_CREATE_PHY_LINK:
+               hci_cs_create_phylink(hdev, ev->status);
                break;
 
-       case HCI_OP_EXIT_SNIFF_MODE:
-               hci_cs_exit_sniff_mode(hdev, ev->status);
+       case HCI_OP_ACCEPT_PHY_LINK:
+               hci_cs_accept_phylink(hdev, ev->status);
                break;
 
-       case HCI_OP_DISCONNECT:
-               hci_cs_disconnect(hdev, ev->status);
+       case HCI_OP_SNIFF_MODE:
+               hci_cs_sniff_mode(hdev, ev->status);
                break;
 
-       case HCI_OP_CREATE_PHY_LINK:
-               hci_cs_create_phylink(hdev, ev->status);
+       case HCI_OP_EXIT_SNIFF_MODE:
+               hci_cs_exit_sniff_mode(hdev, ev->status);
                break;
 
-       case HCI_OP_ACCEPT_PHY_LINK:
-               hci_cs_accept_phylink(hdev, ev->status);
+       case HCI_OP_SWITCH_ROLE:
+               hci_cs_switch_role(hdev, ev->status);
                break;
 
        case HCI_OP_LE_CREATE_CONN:
@@ -2913,6 +2959,13 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
        }
 }
 
+static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_ev_hardware_error *ev = (void *) skb->data;
+
+       BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
+}
+
 static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_role_change *ev = (void *) skb->data;
@@ -3138,6 +3191,38 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
+{
+       if (key_type == HCI_LK_CHANGED_COMBINATION)
+               return;
+
+       conn->pin_length = pin_len;
+       conn->key_type = key_type;
+
+       switch (key_type) {
+       case HCI_LK_LOCAL_UNIT:
+       case HCI_LK_REMOTE_UNIT:
+       case HCI_LK_DEBUG_COMBINATION:
+               return;
+       case HCI_LK_COMBINATION:
+               if (pin_len == 16)
+                       conn->pending_sec_level = BT_SECURITY_HIGH;
+               else
+                       conn->pending_sec_level = BT_SECURITY_MEDIUM;
+               break;
+       case HCI_LK_UNAUTH_COMBINATION_P192:
+       case HCI_LK_UNAUTH_COMBINATION_P256:
+               conn->pending_sec_level = BT_SECURITY_MEDIUM;
+               break;
+       case HCI_LK_AUTH_COMBINATION_P192:
+               conn->pending_sec_level = BT_SECURITY_HIGH;
+               break;
+       case HCI_LK_AUTH_COMBINATION_P256:
+               conn->pending_sec_level = BT_SECURITY_FIPS;
+               break;
+       }
+}
+
 static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_link_key_req *ev = (void *) skb->data;
@@ -3164,6 +3249,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
        if (conn) {
+               clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
+
                if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
                     key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
                    conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
@@ -3179,8 +3266,7 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
                        goto not_found;
                }
 
-               conn->key_type = key->type;
-               conn->pin_length = key->pin_len;
+               conn_set_key(conn, key->type, key->pin_len);
        }
 
        bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -3210,16 +3296,15 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-       if (conn) {
-               hci_conn_hold(conn);
-               conn->disc_timeout = HCI_DISCONN_TIMEOUT;
-               pin_len = conn->pin_length;
+       if (!conn)
+               goto unlock;
 
-               if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
-                       conn->key_type = ev->key_type;
+       hci_conn_hold(conn);
+       conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+       hci_conn_drop(conn);
 
-               hci_conn_drop(conn);
-       }
+       set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
+       conn_set_key(conn, ev->key_type, conn->pin_length);
 
        if (!test_bit(HCI_MGMT, &hdev->dev_flags))
                goto unlock;
@@ -3229,6 +3314,12 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (!key)
                goto unlock;
 
+       /* Update connection information since adding the key will have
+        * fixed up the type in the case of changed combination keys.
+        */
+       if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
+               conn_set_key(conn, key->type, key->pin_len);
+
        mgmt_new_link_key(hdev, key, persistent);
 
        /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
@@ -3238,15 +3329,16 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
         */
        if (key->type == HCI_LK_DEBUG_COMBINATION &&
            !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
-               list_del(&key->list);
-               kfree(key);
-       } else if (conn) {
-               if (persistent)
-                       clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
-               else
-                       set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
+               list_del_rcu(&key->list);
+               kfree_rcu(key, rcu);
+               goto unlock;
        }
 
+       if (persistent)
+               clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
+       else
+               set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
+
 unlock:
        hci_dev_unlock(hdev);
 }
@@ -3424,9 +3516,7 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
                cp.pscan_rep_mode = 0x02;
                hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
        } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-               mgmt_device_connected(hdev, &conn->dst, conn->type,
-                                     conn->dst_type, 0, NULL, 0,
-                                     conn->dev_class);
+               mgmt_device_connected(hdev, conn, 0, NULL, 0);
 
        if (!hci_outgoing_auth_needed(hdev, conn)) {
                conn->state = BT_CONNECTED;
@@ -3895,8 +3985,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
         * event gets always produced as initiator and is also mapped to
         * the mgmt_auth_failed event */
        if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status)
-               mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type,
-                                ev->status);
+               mgmt_auth_failed(conn, ev->status);
 
        hci_conn_drop(conn);
 
@@ -3941,16 +4030,14 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 
        data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
        if (data) {
-               if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
+               if (bredr_sc_enabled(hdev)) {
                        struct hci_cp_remote_oob_ext_data_reply cp;
 
                        bacpy(&cp.bdaddr, &ev->bdaddr);
                        memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
-                       memcpy(cp.randomizer192, data->randomizer192,
-                              sizeof(cp.randomizer192));
+                       memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
                        memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
-                       memcpy(cp.randomizer256, data->randomizer256,
-                              sizeof(cp.randomizer256));
+                       memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
 
                        hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
                                     sizeof(cp), &cp);
@@ -3959,8 +4046,7 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
 
                        bacpy(&cp.bdaddr, &ev->bdaddr);
                        memcpy(cp.hash, data->hash192, sizeof(cp.hash));
-                       memcpy(cp.randomizer, data->randomizer192,
-                              sizeof(cp.randomizer));
+                       memcpy(cp.rand, data->rand192, sizeof(cp.rand));
 
                        hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
                                     sizeof(cp), &cp);
@@ -4188,16 +4274,16 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
                conn->dst_type = irk->addr_type;
        }
 
-       if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
-               addr_type = BDADDR_LE_PUBLIC;
-       else
-               addr_type = BDADDR_LE_RANDOM;
-
        if (ev->status) {
                hci_le_conn_failed(conn, ev->status);
                goto unlock;
        }
 
+       if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
+               addr_type = BDADDR_LE_PUBLIC;
+       else
+               addr_type = BDADDR_LE_RANDOM;
+
        /* Drop the connection if the device is blocked */
        if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) {
                hci_conn_drop(conn);
@@ -4205,8 +4291,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        }
 
        if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-               mgmt_device_connected(hdev, &conn->dst, conn->type,
-                                     conn->dst_type, 0, NULL, 0, NULL);
+               mgmt_device_connected(hdev, conn, 0, NULL, 0);
 
        conn->sec_level = BT_SECURITY_LOW;
        conn->handle = __le16_to_cpu(ev->handle);
@@ -4220,11 +4305,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 
        hci_proto_connect_cfm(conn, ev->status);
 
-       params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
+                                          conn->dst_type);
        if (params) {
                list_del_init(&params->action);
                if (params->conn) {
                        hci_conn_drop(params->conn);
+                       hci_conn_put(params->conn);
                        params->conn = NULL;
                }
        }
@@ -4258,25 +4345,26 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
 }
 
 /* This function requires the caller holds hdev->lock */
-static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
-                                 u8 addr_type, u8 adv_type)
+static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
+                                             bdaddr_t *addr,
+                                             u8 addr_type, u8 adv_type)
 {
        struct hci_conn *conn;
        struct hci_conn_params *params;
 
        /* If the event is not connectable don't proceed further */
        if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
-               return;
+               return NULL;
 
        /* Ignore if the device is blocked */
        if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
-               return;
+               return NULL;
 
        /* Most controller will fail if we try to create new connections
         * while we have an existing one in slave role.
         */
        if (hdev->conn_hash.le_num_slave > 0)
-               return;
+               return NULL;
 
        /* If we're not connectable only connect devices that we have in
         * our pend_le_conns list.
@@ -4284,7 +4372,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
        params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
                                           addr, addr_type);
        if (!params)
-               return;
+               return NULL;
 
        switch (params->auto_connect) {
        case HCI_AUTO_CONN_DIRECT:
@@ -4293,7 +4381,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
                 * incoming connections from slave devices.
                 */
                if (adv_type != LE_ADV_DIRECT_IND)
-                       return;
+                       return NULL;
                break;
        case HCI_AUTO_CONN_ALWAYS:
                /* Devices advertising with ADV_IND or ADV_DIRECT_IND
@@ -4304,7 +4392,7 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
                 */
                break;
        default:
-               return;
+               return NULL;
        }
 
        conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
@@ -4316,8 +4404,8 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
                 * the parameters get removed and keep the reference
                 * count consistent once the connection is established.
                 */
-               params->conn = conn;
-               return;
+               params->conn = hci_conn_get(conn);
+               return conn;
        }
 
        switch (PTR_ERR(conn)) {
@@ -4330,7 +4418,10 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
                break;
        default:
                BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
+               return NULL;
        }
+
+       return NULL;
 }
 
 static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
@@ -4338,6 +4429,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
 {
        struct discovery_state *d = &hdev->discovery;
        struct smp_irk *irk;
+       struct hci_conn *conn;
        bool match;
        u32 flags;
 
@@ -4349,7 +4441,14 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
        }
 
        /* Check if we have been requested to connect to this device */
-       check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
+       conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
+       if (conn && type == LE_ADV_IND) {
+               /* Store report for later inclusion by
+                * mgmt_device_connected
+                */
+               memcpy(conn->le_adv_data, data, len);
+               conn->le_adv_data_len = len;
+       }
 
        /* Passive scanning shouldn't trigger any device found events,
         * except for devices marked as CONN_REPORT for which we do send
@@ -4494,17 +4593,24 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
        if (conn == NULL)
                goto not_found;
 
-       ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
-       if (ltk == NULL)
+       ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
+       if (!ltk)
                goto not_found;
 
+       if (smp_ltk_is_sc(ltk)) {
+               /* With SC both EDiv and Rand are set to zero */
+               if (ev->ediv || ev->rand)
+                       goto not_found;
+       } else {
+               /* For non-SC keys check that EDiv and Rand match */
+               if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
+                       goto not_found;
+       }
+
        memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
        cp.handle = cpu_to_le16(conn->handle);
 
-       if (ltk->authenticated)
-               conn->pending_sec_level = BT_SECURITY_HIGH;
-       else
-               conn->pending_sec_level = BT_SECURITY_MEDIUM;
+       conn->pending_sec_level = smp_ltk_sec_level(ltk);
 
        conn->enc_key_size = ltk->enc_size;
 
@@ -4518,8 +4624,8 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
         */
        if (ltk->type == SMP_STK) {
                set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
-               list_del(&ltk->list);
-               kfree(ltk);
+               list_del_rcu(&ltk->list);
+               kfree_rcu(ltk, rcu);
        } else {
                clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
        }
@@ -4727,6 +4833,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cmd_status_evt(hdev, skb);
                break;
 
+       case HCI_EV_HARDWARE_ERROR:
+               hci_hardware_error_evt(hdev, skb);
+               break;
+
        case HCI_EV_ROLE_CHANGE:
                hci_role_change_evt(hdev, skb);
                break;