2013-04-29 21:51:25

by Alex Deymo

[permalink] [raw]
Subject: Paired devices in discovery mode

Hi!
I'm wonder to solve the following situation:
1. You pair your BT device with your computer and use it.
2. Then go somewhere else and pair it with another computer to use it there.
3. Finally you go back to the first computer and want to use the
device again with the first computer.

In this situation, depending on the device, the first pairing could be
lost if the device supports only one pairing. Some mice/keyboards
support only one pairing, but there are also other devices supporting
more than one pairing at each time.

If the device lost the pairing, the connect attempt with the device
will likely reject our link key. With the current BlueZ, this is
"Paired: yes" for us, but we can't initiate the secure connection. To
solve this we would need to, in order:
1. Remove the device.
2. Wait for the device to appear in the discovery session.
3. Pair again with the device (re-trust is if needed, etc).

Can we solve this or make it easier?
I'm thinking about adding a "Discovering" boolean property to the
Device1 interface that tells you if a device (paired or not, connected
or not) is in discovery mode. We know that because we see an inquiry
response while discovering. I would also modify the "Pair" method to
allow to re-pair a device that is Paired and Discovering instead of
returning an error for that case.
What do you think?

Alex.


2013-04-30 07:23:35

by Johan Hedberg

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

Hi Alex,

On Mon, Apr 29, 2013, Alex Deymo wrote:
> I'm wonder to solve the following situation:
> 1. You pair your BT device with your computer and use it.
> 2. Then go somewhere else and pair it with another computer to use it there.
> 3. Finally you go back to the first computer and want to use the
> device again with the first computer.
>
> In this situation, depending on the device, the first pairing could be
> lost if the device supports only one pairing. Some mice/keyboards
> support only one pairing, but there are also other devices supporting
> more than one pairing at each time.
>
> If the device lost the pairing, the connect attempt with the device
> will likely reject our link key. With the current BlueZ, this is
> "Paired: yes" for us, but we can't initiate the secure connection. To
> solve this we would need to, in order:
> 1. Remove the device.
> 2. Wait for the device to appear in the discovery session.
> 3. Pair again with the device (re-trust is if needed, etc).
>
> Can we solve this or make it easier?
> I'm thinking about adding a "Discovering" boolean property to the
> Device1 interface that tells you if a device (paired or not, connected
> or not) is in discovery mode. We know that because we see an inquiry
> response while discovering. I would also modify the "Pair" method to
> allow to re-pair a device that is Paired and Discovering instead of
> returning an error for that case.
> What do you think?

This has been discussed many times in the past but nothing concrete has
been done about it so far. The core spec essentially gives us two
options: either to reject the link or to ask the user if it's ok to
repair (and loose the old key) and then proceed with repairing. We've so
far only implemented the first option.

I don't think it should be necessary to add any new properties or even
modify the existing behavior of Device1.Pair() though. Instead this
could be done through the normal L2CAP/RFCOMM client socket connect
operation, i.e. Device1.Connect(). We could either introduce a new agent
callback to authorize the repairing or extend the existing
RequestAuthorization callback which is similar to this.

The main thing to keep in mind is to not expose us to spoofing attacks
where some device pretends to be the one we paired with (by having the
same bdaddr) but doesn't have the link key. The first thing to ensure
here is that we do not throw away the old link key until the new pairing
completed successfully. Another thing to ensure is that we do not allow
downgrading the old key, i.e. if the old key was an authenticated one we
must reject an unauthenticated key in the repairing.

All of the above steps could be taken care of by the kernel when it
detects that the remote side doesn't have the key. It'd postpone
indicating completion for the client socket connect() and go ahead with
the necessary steps, including doing a mgmt event to trigger the
Agent1.RequestAuthorization callback.

Johan

2013-05-17 05:07:24

by Marcel Holtmann

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

Hi Scott,

>>> Mac OS have done a good job here, displaying already paired devices in
>>> the Bluetooth Setup Assistant when they are in discovery mode. If you
>>> attempt to pair to one of those devices it will ask you about
>>> un-pairing and re-pairing with that device, and loosing the previous
>>> linkkey there (see screenshot here http://goo.gl/fGJ2U ). Only the
>>> paired devices that are in discovery are shown there in the list.
>>
>> I'm not completely convinced that this is the most user friendly
>> approach (requiring the user to go through a pairing wizard instead of
>> just selecting to connect to the device and having that trigger
>> pairing).
>>
>
> Part of the problem we're seeing is that users instinctively go
> through the pairing wizard each time, and expect to find the device
> there.
>
> I think this is a side-effect of the documentation that comes with
> devices, they tell the user to hold down the connect button when
> turning it on, and then go to the pairing wizard each time.
>
> Because the device is paired, we don't show it in the pairing wizard,
> and BlueZ doesn't give us a hint that it's responding to Inquiry Scans
> so _should_ appear in the pairing wizard again.

that is why I like the iOS approach here. You just get one list about YOUR devices and then it just starts scanning to see if there are other around it might want you to see additionally.

Adding a LastSeen property is mostly useless since device will not go that often visible anyway. So a lot of information for nothing. Maybe a boolean for Discovered could help us to differentiate here. I am though not 100% convinced.

Regards

Marcel


2013-05-15 16:20:23

by Scott James Remnant

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

On Tue, May 14, 2013 at 1:26 AM, Johan Hedberg <[email protected]> wrote:

>> Mac OS have done a good job here, displaying already paired devices in
>> the Bluetooth Setup Assistant when they are in discovery mode. If you
>> attempt to pair to one of those devices it will ask you about
>> un-pairing and re-pairing with that device, and loosing the previous
>> linkkey there (see screenshot here http://goo.gl/fGJ2U ). Only the
>> paired devices that are in discovery are shown there in the list.
>
> I'm not completely convinced that this is the most user friendly
> approach (requiring the user to go through a pairing wizard instead of
> just selecting to connect to the device and having that trigger
> pairing).
>

Part of the problem we're seeing is that users instinctively go
through the pairing wizard each time, and expect to find the device
there.

I think this is a side-effect of the documentation that comes with
devices, they tell the user to hold down the connect button when
turning it on, and then go to the pairing wizard each time.

Because the device is paired, we don't show it in the pairing wizard,
and BlueZ doesn't give us a hint that it's responding to Inquiry Scans
so _should_ appear in the pairing wizard again.

Scott

2013-05-15 12:22:30

by Marcel Holtmann

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

Hi Johan,

>> Mac OS have done a good job here, displaying already paired devices in
>> the Bluetooth Setup Assistant when they are in discovery mode. If you
>> attempt to pair to one of those devices it will ask you about
>> un-pairing and re-pairing with that device, and loosing the previous
>> linkkey there (see screenshot here http://goo.gl/fGJ2U ). Only the
>> paired devices that are in discovery are shown there in the list.
>
> I'm not completely convinced that this is the most user friendly
> approach (requiring the user to go through a pairing wizard instead of
> just selecting to connect to the device and having that trigger
> pairing).

yes, back in the days MacOS has done an awesome job to make Bluetooth more user accessible. However these days I would rather look towards iOS if you want to get inspiration.

If I would have to write a desktop UI for Bluetooth right now, I would not go with a pairing wizard at all. I would go with a device menu/list like iOS does.

>> The problem is that I can't implement such a nice interface with the
>> current BlueZ API, since I don't known when a paired device is
>> replying to the inquiry request or not. BlueZ knows that, but I don't
>> know that from the dbus API. That's why I want to introduce the
>> "Discovering" property.
>
> If we're really going to introduce something like this I'd rather have a
> "LastSeen" property with the time that the device was last seen. This
> could potentially be useful for sorting the devices in the UI (something
> that a simple "Discovering" boolean doesn't allow).

What would a last seen improve here? Maybe I am missing a bit of context. How many devices are we expecting to have paired. In a normal day use you have around 3-4. And even power users don't get easily over 10. I do understand that with LE this potentially can change, but so far I have not seen that. Users just don't have that many devices.

>> It will be also handy if Device1.Pair() allows me to re-pair the
>> device and only replaces the linkkey if the pairing works. Right now,
>> if the user wants to re-pair a device it has to remove it, wait
>> several seconds until it appears in a discovery session and then call
>> Pair in that new device. This possible, but not as user-friendly as it
>> could be, and the change I'm proposing is backward compatible with the
>> existing users since the only changed behavior is when trying to Pair
>> an already Paired device.
>
> I agree that we should consider allowing multiple calls to Pair(). If we
> have an existing link key the procedure would just drop the old one as
> soon as repairing has succeeded.

I am fine with Device1.Pair() triggering a repairing. We could just ask via the agent the user to confirm that he/she wants to drop the previous link and be done with it. Simple, intuitive and exactly a user interaction we want do see. And more important a question that the user can answer at that point in time since he/she pressed the pairing button. And in addition, the user can abort the pairing attempt if it was an accident. If any UI system wants to outsmart us or the user, it can hook into the agent to do so.

Regards

Marcel


2013-05-14 08:26:18

by Johan Hedberg

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

Hi Alex,

On Fri, May 10, 2013, Alex Deymo wrote:
> On Tue, Apr 30, 2013 at 12:23 AM, Johan Hedberg <[email protected]> wrote:
> > This has been discussed many times in the past but nothing concrete has
> > been done about it so far. The core spec essentially gives us two
> > options: either to reject the link or to ask the user if it's ok to
> > repair (and loose the old key) and then proceed with repairing. We've so
> > far only implemented the first option.
>
> I think that in that the first option is ok if the connection is
> initiated by the device, since it could be a malicious device with a
> fake key trying to spam us. But if we reject and ignore the key
> provided by the device (or the devices doesn't know it), we still need
> to give the user a way to re-pair the device.

Agreed.

> I don't like the idea of extending the Device1.Connect() method with
> pairing related stuff,

We wouldn't really be extending it. Connect() has always had the
capability of triggering General Bonding, and that's what it'll e.g. do
if you call it without calling Pair() first.

> since some devices (mostly mice) are not normally-connectable and we
> should not expect the Connect() to work for those devices.

If the other device requires some action to make it connectable/pairable
then there's no difference between Connect() or Pair() - you still need
to take that action on the remote device. The only difference is that
Connect() will trigger General Bonding whereas Pair() will trigger
Dedicated Bonding.

> Also, if the device supports encryption but don't require it (like
> keyboards), the way I have to tell BlueZ that I want an encrypted
> connection is to Pair the device first, and make sure the
> device is Paired before Connect.

True, though it should be noted here that this is only applicable for
older pre-2.1 devices doing legacy pairing.

> Mac OS have done a good job here, displaying already paired devices in
> the Bluetooth Setup Assistant when they are in discovery mode. If you
> attempt to pair to one of those devices it will ask you about
> un-pairing and re-pairing with that device, and loosing the previous
> linkkey there (see screenshot here http://goo.gl/fGJ2U ). Only the
> paired devices that are in discovery are shown there in the list.

I'm not completely convinced that this is the most user friendly
approach (requiring the user to go through a pairing wizard instead of
just selecting to connect to the device and having that trigger
pairing).

> The problem is that I can't implement such a nice interface with the
> current BlueZ API, since I don't known when a paired device is
> replying to the inquiry request or not. BlueZ knows that, but I don't
> know that from the dbus API. That's why I want to introduce the
> "Discovering" property.

If we're really going to introduce something like this I'd rather have a
"LastSeen" property with the time that the device was last seen. This
could potentially be useful for sorting the devices in the UI (something
that a simple "Discovering" boolean doesn't allow).

> It will be also handy if Device1.Pair() allows me to re-pair the
> device and only replaces the linkkey if the pairing works. Right now,
> if the user wants to re-pair a device it has to remove it, wait
> several seconds until it appears in a discovery session and then call
> Pair in that new device. This possible, but not as user-friendly as it
> could be, and the change I'm proposing is backward compatible with the
> existing users since the only changed behavior is when trying to Pair
> an already Paired device.

I agree that we should consider allowing multiple calls to Pair(). If we
have an existing link key the procedure would just drop the old one as
soon as repairing has succeeded.

Johan

2013-05-11 02:36:29

by Alex Deymo

[permalink] [raw]
Subject: Re: Paired devices in discovery mode

Hi Johan,

On Tue, Apr 30, 2013 at 12:23 AM, Johan Hedberg <[email protected]> wrote:
> This has been discussed many times in the past but nothing concrete has
> been done about it so far. The core spec essentially gives us two
> options: either to reject the link or to ask the user if it's ok to
> repair (and loose the old key) and then proceed with repairing. We've so
> far only implemented the first option.

I think that in that the first option is ok if the connection is
initiated by the device, since it could be a malicious device with a
fake key trying to spam us. But if we reject and ignore the key
provided by the device (or the devices doesn't know it), we still need
to give the user a way to re-pair the device.

I don't like the idea of extending the Device1.Connect() method with
pairing related stuff, since some devices (mostly mice) are not
normally-connectable and we should not expect the Connect() to work
for those devices. Also, if the device supports encryption but don't
require it (like keyboards), the way I have to tell BlueZ that I want
an encrypted connection is to Pair the device first, and make sure the
device is Paired before Connect. We would have to make sure then that
Connect() a device reported as Paired does ensure a encrypted even
after repair, and also I will require the client to register an agent
before calling Connect() just in case the connect requires it... and
currently we don't need that.

Mac OS have done a good job here, displaying already paired devices in
the Bluetooth Setup Assistant when they are in discovery mode. If you
attempt to pair to one of those devices it will ask you about
un-pairing and re-pairing with that device, and loosing the previous
linkkey there (see screenshot here http://goo.gl/fGJ2U ). Only the
paired devices that are in discovery are shown there in the list.

The problem is that I can't implement such a nice interface with the
current BlueZ API, since I don't known when a paired device is
replying to the inquiry request or not. BlueZ knows that, but I don't
know that from the dbus API. That's why I want to introduce the
"Discovering" property. It will be also handy if Device1.Pair() allows
me to re-pair the device and only replaces the linkkey if the pairing
works. Right now, if the user wants to re-pair a device it has to
remove it, wait several seconds until it appears in a discovery
session and then call Pair in that new device. This possible, but not
as user-friendly as it could be, and the change I'm proposing is
backward compatible with the existing users since the only changed
behavior is when trying to Pair an already Paired device.

Alex.