Hi everyone,
I’m working on a BLE peripheral using the NimBLE stack running on an
ESP32. I’m really struggling to get pairing/bonding/security to work how
I need and was hoping I could get some help here.
The key requirements in question are as follows:
- A central must be bonded in order for it to be able to interact with
any of the peripheral’s characteristics in any way.
- Only one central can be bonded, and that bonded central is the only
one that is allowed to be connected to the peripheral (I have a button
to delete the bond so that a new central can bond).
This is supposed to work exactly like a smartwatch or wireless keyboard:
you must pair it with your phone; nothing else except your phone can
then access it; and you have to unpair it to use it with another phone.
So my question is how do I implement this with the NimBLE stack and what
is the best approach to enforcing these security requirements?
Here are two approaches that I have been trying to make work:
1) Call ble_gap_security_initiate() in the BLE_GAP_EVENT_CONNECT event
to explicitly ensure that connections are secure whenever they are
started. I've been having multiple issues with this from the Android
point-of-view, such as it asking for pairing when connecting but already
paired, getting pairing-related dialogs show multiple times, and having
to tap the device in Android Settings multiple times to get the pairing
pin dialog to open. Overall I don’t have much confidence in this due to
all of the issues I’ve experienced, and a lack of understanding of how
it, and the bond restoration process in general, works.
2) Security is not explicitly requested and the device simply doesn’t
respond to characteristic interactions unless the connection is secure.
To interact with the characteristics, you must first pair it manually
(e.g. in Android Settings or within a companion app that would be
developed). The biggest difficulty I have with this is that I need to
terminate any connection that does not successfully bond or restore a
bond. I can use ble_store_read_our_sec() to check if there is a bond for
the current connection, but I haven’t found a way to determine if that
bond fails to actually restore. I’m left with using timers to terminate
the connection if the BLE_GAP_EVENT_ENC_CHANGE event isn't received in a
certain amount of time. Another thing I tried was to use directed
advertising but iOS doesn’t support that.
An additional complexity is that things need to work with RPA addresses,
as at least iOS uses them when advertising, and I would like to use
privacy on the peripheral.
So, how should I do this? There is limited information and questions on
the internet regarding NimBLE pairing and security. I’ve been trawling
through the NimBLE source code and the source code of other BLE
libraries even, trying to figure out how to get this working. So I’m
really hoping I can get some help here.
Thanks,
Henry