Hi, On Thu, 1 Sept 2022 at 17:01, Henry Hunt <henry.h...@spt93.com> wrote:
> 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. This double pairing dialog on Android seems to be Android issue as this happens with other BLE stacks too. While sending SecurityRequest on connection is fine I suggest other design on peripheral device. Set required security on GATT characteristic (eg BLE_GATT_CHR_F_READ_ENC) and when peer reads/write to it it will get ATT error due to insufficient security. Most (all?) BLE stacks will in such case start pairing (or enable encryption if already bonded) and re-try GATT operation. > 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. > Upstream NimBLE host stack requires Privacy 1.2 support in controller as RPA resolving and generation is implemented only in NimBLE controller. In such case using privacy requires to pass proper own_addr type with value +2 (ie 0x02 if using public addr or 0x03 if static random addr is used). Unfortunately setting custom local IRK currently required using ble_hs_pvcy_set_our_irk() which is private function (src/ble_hs_pvcy_priv.h). This is something we plan to improve when have some spare time... You are using ESP32 port which has own controller AFAIR without privacy 1.2 support, I think ESP32 has some modifications on top of NimBLE to handle privacy in host. Since this isin't upstream code you should ask in fork community. There were some interest in adding host based privacy support to NimBLE but it seems like it never ended in creating a PR. See https://github.com/apache/mynewt-nimble/issues/897 for some details. -- pozdrawiam Szymon K. Janc