Skip to content

Commit

Permalink
Merge tag 'for-net-2025-05-08' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/bluetooth/bluetooth

Luiz Augusto von Dentz says:

====================
bluetooth pull request for net:

 - MGMT: Fix MGMT_OP_ADD_DEVICE invalid device flags
 - hci_event: Fix not using key encryption size when its known

* tag 'for-net-2025-05-08' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth:
  Bluetooth: hci_event: Fix not using key encryption size when its known
  Bluetooth: MGMT: Fix MGMT_OP_ADD_DEVICE invalid device flags
====================

Link: https://patch.msgid.link/20250508150927.385675-1-luiz.dentz@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed May 9, 2025
2 parents 2c89c1b + c82b635 commit ea9a83d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 34 deletions.
1 change: 1 addition & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1798,6 +1798,7 @@ struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
void hci_uuids_clear(struct hci_dev *hdev);

void hci_link_keys_clear(struct hci_dev *hdev);
u8 *hci_conn_key_enc_size(struct hci_conn *conn);
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
bdaddr_t *bdaddr, u8 *val, u8 type,
Expand Down
24 changes: 24 additions & 0 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -3023,3 +3023,27 @@ void hci_conn_tx_dequeue(struct hci_conn *conn)

kfree_skb(skb);
}

u8 *hci_conn_key_enc_size(struct hci_conn *conn)
{
if (conn->type == ACL_LINK) {
struct link_key *key;

key = hci_find_link_key(conn->hdev, &conn->dst);
if (!key)
return NULL;

return &key->pin_len;
} else if (conn->type == LE_LINK) {
struct smp_ltk *ltk;

ltk = hci_find_ltk(conn->hdev, &conn->dst, conn->dst_type,
conn->role);
if (!ltk)
return NULL;

return &ltk->enc_size;
}

return NULL;
}
73 changes: 42 additions & 31 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,17 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
handle);
conn->enc_key_size = 0;
} else {
u8 *key_enc_size = hci_conn_key_enc_size(conn);

conn->enc_key_size = rp->key_size;
status = 0;

if (conn->enc_key_size < hdev->min_enc_key_size) {
/* Attempt to check if the key size is too small or if it has
* been downgraded from the last time it was stored as part of
* the link_key.
*/
if (conn->enc_key_size < hdev->min_enc_key_size ||
(key_enc_size && conn->enc_key_size < *key_enc_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
Expand All @@ -755,6 +762,10 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
}

/* Update the key encryption size with the connection one */
if (key_enc_size && *key_enc_size != conn->enc_key_size)
*key_enc_size = conn->enc_key_size;
}

hci_encrypt_cfm(conn, status);
Expand Down Expand Up @@ -3065,6 +3076,34 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, void *edata,
hci_dev_unlock(hdev);
}

static int hci_read_enc_key_size(struct hci_dev *hdev, struct hci_conn *conn)
{
struct hci_cp_read_enc_key_size cp;
u8 *key_enc_size = hci_conn_key_enc_size(conn);

if (!read_key_size_capable(hdev)) {
conn->enc_key_size = HCI_LINK_KEY_SIZE;
return -EOPNOTSUPP;
}

bt_dev_dbg(hdev, "hcon %p", conn);

memset(&cp, 0, sizeof(cp));
cp.handle = cpu_to_le16(conn->handle);

/* If the key enc_size is already known, use it as conn->enc_key_size,
* otherwise use hdev->min_enc_key_size so the likes of
* l2cap_check_enc_key_size don't fail while waiting for
* HCI_OP_READ_ENC_KEY_SIZE response.
*/
if (key_enc_size && *key_enc_size)
conn->enc_key_size = *key_enc_size;
else
conn->enc_key_size = hdev->min_enc_key_size;

return hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
}

static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
Expand Down Expand Up @@ -3157,23 +3196,11 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
ev->link_type == ACL_LINK) {
struct link_key *key;
struct hci_cp_read_enc_key_size cp;

key = hci_find_link_key(hdev, &ev->bdaddr);
if (key) {
set_bit(HCI_CONN_ENCRYPT, &conn->flags);

if (!read_key_size_capable(hdev)) {
conn->enc_key_size = HCI_LINK_KEY_SIZE;
} else {
cp.handle = cpu_to_le16(conn->handle);
if (hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE,
sizeof(cp), &cp)) {
bt_dev_err(hdev, "sending read key size failed");
conn->enc_key_size = HCI_LINK_KEY_SIZE;
}
}

hci_read_enc_key_size(hdev, conn);
hci_encrypt_cfm(conn, ev->status);
}
}
Expand Down Expand Up @@ -3612,24 +3639,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,

/* 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;

/* Only send HCI_Read_Encryption_Key_Size if the
* controller really supports it. If it doesn't, assume
* the default size (16).
*/
if (!read_key_size_capable(hdev)) {
conn->enc_key_size = HCI_LINK_KEY_SIZE;
goto notify;
}

cp.handle = cpu_to_le16(conn->handle);
if (hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE,
sizeof(cp), &cp)) {
bt_dev_err(hdev, "sending read key size failed");
conn->enc_key_size = HCI_LINK_KEY_SIZE;
if (hci_read_enc_key_size(hdev, conn))
goto notify;
}

goto unlock;
}
Expand Down
9 changes: 6 additions & 3 deletions net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7506,11 +7506,16 @@ static void add_device_complete(struct hci_dev *hdev, void *data, int err)
struct mgmt_cp_add_device *cp = cmd->param;

if (!err) {
struct hci_conn_params *params;

params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));

device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type,
cp->action);
device_flags_changed(NULL, hdev, &cp->addr.bdaddr,
cp->addr.type, hdev->conn_flags,
PTR_UINT(cmd->user_data));
params ? params->flags : 0);
}

mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE,
Expand Down Expand Up @@ -7613,8 +7618,6 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
goto unlock;
}

cmd->user_data = UINT_PTR(current_flags);

err = hci_cmd_sync_queue(hdev, add_device_sync, cmd,
add_device_complete);
if (err < 0) {
Expand Down

0 comments on commit ea9a83d

Please sign in to comment.