h2zero / esp-nimble-cpp

C++ library for the esp32 NimBLE stack based on and mostly compatible with @nkolban cpp_utils BLE library.
https://h2zero.github.io/esp-nimble-cpp/
Apache License 2.0
158 stars 60 forks source link

How to allow only bonded connections to connect, depending on the device mode #160

Closed cmorganBE closed 1 day ago

cmorganBE commented 1 month ago

Goal is to permit connecting and bonding when in 'connecting and bonding mode', and only permit connections of previously bonded centrals when not in 'connecting and bonding mode'.

My approach was to try to use whitelists and setScanFilter(true, true) for the 'connecting and bonding mode', and setScanFilter(false, false) for the other mode.

This seems to imply that the application would have to track addresses, store them in nvs, restore them at application start up etc but this seems complex.

I did try some hardcoded use of whiteListAdd() as a proof of concept but it looks like RPA is messing things up.

Thoughts?

h2zero commented 1 month ago

If your goal is to allow only bonded devices to connect until the mode changes you can simply disconnect any device that is not bonded with yours by testing the NimBLEConnInfo:isBonded() return value in the onConnect() callback.

FYI, adding devices to the whitelist automatically stores the info in NVS and should not need to be maintained by the app. The RPA should not be an issue with the esp32-s3 as I believe you are using.

related: https://github.com/h2zero/NimBLE-Arduino/issues/651

cmorganBE commented 1 month ago

I had looked at this approach but it looks like bonding isn't known at the time of onConnect()?

NOTE: The whitelist comment isn't correct, that's old text, the condition used is:

        if(!(pBleImpl->GetConnectMode() == IBle::ConnectMode::Any) && !connInfo.isBonded())
I (87223) BLE: onConnect
I (87223) NimBLE: GAP procedure initiated: 
I (87223) NimBLE: connection parameter update; conn_handle=1 itvl_min=6 itvl_max=6 latency=0 supervision_timeout=10 min_ce_len=0 max_ce_len=0
I (87223) NimBLE: 

I (87223) BLE: mtu: 23
I (87223) BLE: OTA address 56:ed:2c:1f:5b:15, type 1
I (87223) BLE: ID address 5c:3e:1b:d7:2d:3c, type 0
I (87223) BLE: Bonded: no, Authenticated: no, Encrypted: no, Key size: 0  <------------------------------------
W (87223) BLE: ConnectMode::WhiteList and device is not in whitelist, disconnecting device
I (87223) NimBLE: GAP procedure initiated: terminate connection; conn_handle=1 hci_reason=19

I (87293) BLE: Client disconnected
I (87293) NimBLE: GAP procedure initiated: advertise; 
I (87293) NimBLE: disc_mode=2
I (87293) NimBLE:  adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0
I (87293) NimBLE: 

But I can confirm the device is bonded if I put it into that 'any mode' and connect via lightblue I don't get any pairing prompts.

So it doesn't look like the bond is known when onConnect() occurs.

Note that I rebooted between any mode -> pairing -> reboot device -> text above -> any mode -> able to connect without pairing, so the bond is persisted although I think I've seen issues after several minutes due to the RPA changing but I'm not clera on this.

cmorganBE commented 1 month ago

Here is the output at the very end after going back into 'any mode' and reconnecting, if it helps, although it isn't obvious how to tell if a bond is being created or not.

I (229353) BLE: onConnect
I (229353) NimBLE: GAP procedure initiated: 
I (229353) NimBLE: connection parameter update; conn_handle=1 itvl_min=6 itvl_max=6 latency=0 supervision_timeout=10 min_ce_len=0 max_ce_len=0
I (229353) NimBLE: 

I (229353) BLE: mtu: 23
I (229353) BLE: OTA address 56:ed:2c:1f:5b:15, type 1
I (229353) BLE: ID address 5c:3e:1b:d7:2d:3c, type 0
I (229353) BLE: Bonded: no, Authenticated: no, Encrypted: no, Key size: 0
I (230063) NimBLEServer: mtu update event; conn_handle=1 mtu=251
I (230063) BLE: MTU updated: 251 for connection ID: 1
I (230063) BLE: onAuthenticationComplete()
I (230063) BLE: connection is encrypted
I (230063) BLE: OTA address 56:ed:2c:1f:5b:15, type 1
I (230063) BLE: ID address 5c:3e:1b:d7:2d:3c, type 0
I (230063) BLE: Bonded: yes, Authenticated: no, Encrypted: yes, Key size: 16
I (230063) NimBLEServer: subscribe event; attr_handle=8, subscribed: false
I (241023) main: event queue high water mark 7 of 20
I (350873) NimBLEServer: subscribe event; attr_handle=8, subscribed: false
I (350873) BLE: Client disconnected
I (350873) NimBLE: GAP procedure initiated: advertise; 
I (350873) NimBLE: disc_mode=2
I (350873) NimBLE:  adv_channel_map=0 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0
I (350873) NimBLE: 
h2zero commented 1 month ago

The bonded flag should be set but that may be a bug in the nimble stack. Alternatively you can check isEncrypted and it should be true if a bonded peer connects as well.

cmorganBE commented 1 month ago

@h2zero so sadly isEncrypted is also false in onConnected(), both bonded and isEncrypted are true in onAuthenticated however. You can see from the log above with the <------------ arrow that they are both false.

h2zero commented 1 month ago

Hmm, something has changed in the stack code then. This used to work just fine.

cmorganBE commented 1 month ago

@h2zero would a compact reproducible example help with debug? It could be that I'm doing something incorrect here relative to configuration options.

h2zero commented 1 month ago

Yes, that would be great if you could.

cmorganBE commented 1 month ago

@h2zero https://github.com/cmorganBE/esp-nimble-cpp-test/tree/bonding_with_whitelist_control

I think this is a pretty compact example of what I'm trying to do that runs on the esp32s3-devkit-c1 (or should run on any devkit really as it doesn't require any physical io)

There is a compile time define, WISH_THIS_WORKED that enables using the whitelists and setScanFilter(). If that isn't defined the code tries to use the bonded state in onConnect().

cmorganBE commented 1 month ago

Hey @h2zero have you had a chance to take a look at this yet? I'd be willing to discuss payment around getting this feature working if that would help move it along. My email is cmorgan@boston-engineering.com.

h2zero commented 1 month ago

@cmorganBE, yes I have reproduced the issue here, I will email you tonight.

cmorganBE commented 1 day ago

Resolved for me!