Re: [PATCH v1] adapter: Manage device state of cross-transport SMP keys

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Cheng,

On Mon, Aug 26, 2024 at 3:05 AM Cheng Jiang <quic_chejiang@xxxxxxxxxxx> wrote:
>
> Cross-transport derived ltk/csrk/irk are reported to bluetoothd from
> kernel with BR/EDR address type, and bluetoothd doesn't treat it as LE
> paired/bonded. In this case, bluetoothd won't send remove bond operation
> with LE address type to kernel when executing unpair, so SMP keys are
> retained in kernel list. Then RPA is getting resolved since we still
> have irk which was not deleted when unpair device is done because only
> link key is deleted since addr type is bredr.
>
> What’s more, pair LE of the same address will always fail in kernel
> for ltk existence, and send back AlreadyExists error, but device state
> is still unpaired/unbonded in bluetoothd.
>
> So bluetoothd needs to consider LE paired/bonded when receiving SMP keys
> even if they are cross-transport derived.
> ---
>  src/adapter.c | 53 ++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 40 insertions(+), 13 deletions(-)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index 245de4456..4e5af9579 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -8647,6 +8647,7 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
>         struct btd_adapter *adapter = user_data;
>         struct btd_device *device;
>         char dst[18];
> +       uint8_t addr_type;
>
>         if (length < sizeof(*ev)) {
>                 btd_error(adapter->dev_id, "Too small new link key event");
> @@ -8666,7 +8667,13 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
>                 return;
>         }
>
> -       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr->type);
> +       /*
> +        * For LE public address, key here is cross-transport derived,
> +        * so consider it as BR/EDR public address.
> +        *
> +        */
> +       addr_type = addr->type == BDADDR_LE_PUBLIC ? BDADDR_BREDR : addr->type;
> +       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr_type);
>         if (!device) {
>                 btd_error(adapter->dev_id,
>                                 "Unable to get device object for %s", dst);
> @@ -8682,7 +8689,7 @@ static void new_link_key_callback(uint16_t index, uint16_t length,
>                 device_set_bonded(device, BDADDR_BREDR);
>         }
>
> -       bonding_complete(adapter, &addr->bdaddr, addr->type, 0);
> +       bonding_complete(adapter, &addr->bdaddr, addr_type, 0);
>  }
>
>  static void store_ltk_group(struct btd_adapter *adapter, const bdaddr_t *peer,
> @@ -8773,6 +8780,7 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
>         struct btd_device *device;
>         bool persistent;
>         char dst[18];
> +       uint8_t addr_type;
>
>         if (length < sizeof(*ev)) {
>                 btd_error(adapter->dev_id, "Too small long term key event");
> @@ -8784,7 +8792,13 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
>         DBG("hci%u new LTK for %s type %u enc_size %u",
>                 adapter->dev_id, dst, ev->key.type, ev->key.enc_size);
>
> -       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr->type);
> +       /*
> +        * For BR/EDR public address, key here is cross-transport derived,
> +        * so consider it as LE public address for SMP.
> +        *
> +        */

This is only the case if, an only if, the device is a dual-mode
device, so this probably need to be checked that we don't attempt to
do this regardless.

> +       addr_type = addr->type == BDADDR_BREDR ? BDADDR_LE_PUBLIC : addr->type;
> +       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr_type);
>         if (!device) {
>                 btd_error(adapter->dev_id,
>                                 "Unable to get device object for %s", dst);
> @@ -8802,8 +8816,7 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
>          * be persistently stored.
>          *
>          */
> -       if (addr->type == BDADDR_LE_RANDOM &&
> -                               (addr->bdaddr.b[5] & 0xc0) != 0xc0)
> +       if (addr_type == BDADDR_LE_RANDOM && (addr->bdaddr.b[5] & 0xc0) != 0xc0)
>                 persistent = false;
>         else
>                 persistent = !!ev->store_hint;
> @@ -8817,15 +8830,15 @@ static void new_long_term_key_callback(uint16_t index, uint16_t length,
>                 rand = le64_to_cpu(key->rand);
>
>                 store_longtermkey(adapter, &key->addr.bdaddr,
> -                                       key->addr.type, key->val, key->central,
> +                                       addr_type, key->val, key->central,
>                                         key->type, key->enc_size, ediv, rand);
>
> -               device_set_bonded(device, addr->type);
> +               device_set_bonded(device, addr_type);
>         }
>
>         device_set_ltk(device, ev->key.val, ev->key.central, ev->key.enc_size);
>
> -       bonding_complete(adapter, &addr->bdaddr, addr->type, 0);
> +       bonding_complete(adapter, &addr->bdaddr, addr_type, 0);
>  }
>
>  static void new_csrk_callback(uint16_t index, uint16_t length,
> @@ -8837,6 +8850,7 @@ static void new_csrk_callback(uint16_t index, uint16_t length,
>         struct btd_adapter *adapter = user_data;
>         struct btd_device *device;
>         char dst[18];
> +       uint8_t addr_type;
>
>         if (length < sizeof(*ev)) {
>                 btd_error(adapter->dev_id, "Too small CSRK event");
> @@ -8848,7 +8862,13 @@ static void new_csrk_callback(uint16_t index, uint16_t length,
>         DBG("hci%u new CSRK for %s type %u", adapter->dev_id, dst,
>                                                                 ev->key.type);
>
> -       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr->type);
> +       /*
> +        * For BR/EDR public address, key here is cross-transport derived,
> +        * so consider it as LE public address for SMP.
> +        *
> +        */
> +       addr_type = addr->type == BDADDR_BREDR ? BDADDR_LE_PUBLIC : addr->type;

Ditto.

> +       device = btd_adapter_get_device(adapter, &addr->bdaddr, addr_type);
>         if (!device) {
>                 btd_error(adapter->dev_id,
>                                 "Unable to get device object for %s", dst);
> @@ -8911,6 +8931,7 @@ static void new_irk_callback(uint16_t index, uint16_t length,
>         struct btd_device *device, *duplicate;
>         bool persistent;
>         char dst[18], rpa[18];
> +       uint8_t addr_type;
>
>         if (length < sizeof(*ev)) {
>                 btd_error(adapter->dev_id, "Too small New IRK event");
> @@ -8922,16 +8943,22 @@ static void new_irk_callback(uint16_t index, uint16_t length,
>
>         DBG("hci%u new IRK for %s RPA %s", adapter->dev_id, dst, rpa);
>
> +       /*
> +        * For BR/EDR public address, key here is cross-transport derived,
> +        * so consider it as LE public address for SMP.
> +        *
> +        */
> +       addr_type = addr->type == BDADDR_BREDR ? BDADDR_LE_PUBLIC : addr->type;

Ditto.

>         if (bacmp(&ev->rpa, BDADDR_ANY)) {
>                 device = btd_adapter_get_device(adapter, &ev->rpa,
>                                                         BDADDR_LE_RANDOM);
>                 duplicate = btd_adapter_find_device(adapter, &addr->bdaddr,
> -                                                               addr->type);
> +                                                               addr_type);
>                 if (duplicate == device)
>                         duplicate = NULL;
>         } else {
>                 device = btd_adapter_get_device(adapter, &addr->bdaddr,
> -                                                               addr->type);
> +                                                               addr_type);
>                 duplicate = NULL;
>         }
>
> @@ -8941,7 +8968,7 @@ static void new_irk_callback(uint16_t index, uint16_t length,
>                 return;
>         }
>
> -       device_update_addr(device, &addr->bdaddr, addr->type);
> +       device_update_addr(device, &addr->bdaddr, addr_type);
>
>         if (duplicate)
>                 device_merge_duplicate(device, duplicate);
> @@ -8950,7 +8977,7 @@ static void new_irk_callback(uint16_t index, uint16_t length,
>         if (!persistent)
>                 return;
>
> -       store_irk(adapter, &addr->bdaddr, addr->type, irk->val);
> +       store_irk(adapter, &addr->bdaddr, addr_type, irk->val);
>
>         btd_device_set_temporary(device, false);
>  }
> --
> 2.25.1
>
>


-- 
Luiz Augusto von Dentz





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux