RFC: PoC: Bluetooth secure simple pairing support

From: Andreas Kempe <kempe_at_lysator.liu.se>
Date: Wed, 04 Aug 2021 12:33:48 UTC
Hello everyone,

A few months back I sent a mail titled "Wireless Logitecgh M557 mouse
issues" to the bluetooth list and since then I finally found some time
to do more digging into the issue.

Comparing the FreeBSD behaviour to that of Linux via packet dumps, I
found that the reason my buetooth mouse is not able to reconnect to my
FreeBSD machine is that no pairing is performed. Currently, the
initial connection to the mouse is made and the mouse is used in an
unpaired state. When the mouse tries to reconnect, the computer has no
authentication key and the connection fails.

Attached to this mail, you can find a proof of concept patch for
allowing pairing between my mouse and the FreeBSD host. Using the
attached patch, I'm able to connect my mouse and it reconnects when
switched off and on again. The patch applies on top of Git revision
142f0d36d90979a983e1bb0b69d1d859338b4d90.

Using the PoC
-------------

In its current form, hcsecd has a very rudimentary implementation of
pairing support. No real state machine is used and error handling is
pretty much non-existent. The implementation assumes all operations
went well (which they have always done with my mouse so far).

Using the patch and performing the pairing:

1. Ensure that /var/db/{hcsecd.keys,bthidd.hids} do not contain
   entries fro the mouse.

2. Prep the hcsecd configuration file with the mouse.

device {
	bdaddr	00:1f:20:f5:cd:5f;
	name	"Bluetooth Mouse M557";
	key	nokey;
	pin	nopin;
}

3. Prep the bthidd configuration file.

device {
	bdaddr			00:1f:20:f5:cd:5f;
	name			"Bluetooth Mouse M557";
	vendor_id		0x046d;
	product_id		0xb010;
	version			0x1001;
	control_psm		0x11;
	interrupt_psm		0x13;
	reconnect_initiate	true;
	battery_power		true;
	normally_connectable	false;
	hid_descriptor		{
		[...]
	};
}

4. Start hcsecd.

service hcsecd start

5. Create a connection to the mouse.

hccontrol Create_connection 00:1f:20:f5:cd:5f

Creating the connection causes the pairing to happen.

6. Start bthidd.

service bthidd start

The mouse should now connect and work as intended. After the initial
pairing, the mouse can be turned off and on again and as long as
hcsecd and bthidd are running the mouse should reconnect.

During the initial pairing, bthidd can't be left running since it will
try to connect to the mouse and send HID-related things disturbing the
pairing process.

Questions
---------

Is implementing the pairing in hcsecd the correct approach?

Is a more complex state machine needed or can the expected pairing
flow be hard coded like the PoC albeit with proper error handling?
static int pairing used in the PoC is the only "state machine" state
currently present and should be done in a nicer way, but I deemed it
sufficent for the PoC.

How should one handle the interaction between bthidd and hcsecd? If
one wants the initial to pairing to work, bthidd can't send its
messages until the pairing is completed.

Is my approach to this sane or am I going in the wrong direction?

Looking forward to your feedback!
Cordially,
Andreas Kempe