BLE sequence of characteristic discovery and read with and without pairing/bonding

I'm trying to read the CTS characteristic from a BLE server (an iOS device) and part of the requirement from Apple is that the server and client be paired and bonded before the CTS information is available.

What I'm trying to establish is the chain of events that will occur in terms of pair/bonding, connection, discovery and then reading of the server CTS information, so that I can ensure that my code knows when the CTS info is available.  The two scenarios are (obviously)

  1. Client and server not known to each other, so that pairing/bonding needs to occur first before the CTS info can be read
  2. Client and server have previously paired and bonded, and so do not need to go through this process first before the CTS can be read

I've based my code on the cts_peripheral example, but in this one, a button press is used to trigger the CTS read.  In my code, I want to set a flag to indicate that the CTS is available so that I can read the characteristic info, but what I'm seeing is:

  • connection and discovery will occur regardless of whether the devices are paired/bonded.
  • pairing/bonding seems to occur as the last process in the chain of events

So I can't see clearly see where in the chain of events the CTS info is actually available in these two scenarios.  If I set my flag after pairing/bonding has been completed, then it works OK in the first scenario.  But the callback for pairing/bonding doesn't get called in the second scenario, so I then need to set my flag somewhere in the GATT discovery call backs.  But these seem to get called prior to the pairing/bonding occurring, so this means I attempt to read the CTS info prior to pairing/bonding and the process fails.

Can anyone help me get a clearer path forward here?

Cheers,

Mike

Parents
  • Hi Mike, 

    Could you let me know which SDK version you are using ? 
    If you are using NCS v2.0.x you can have a look at the periphera_uart example. 
    In the example, if you enable CONFIG_BT_NUS_SECURITY_ENABLED, you can find that:

    - On the first bond, after the bonding is finished, you will receive pairing_complete() call back. 

    - On reconnection to a bonded device, you will not receive pairing_complete() but instead receive security_changed() call back. Note that security_changed belong to conn_callbacks when the pairing_complete() belongs to conn_auth_info_callbacks

  • Hi Hung,

    I've been doing a bit more development work on the CTS functionality.  Your suggestion above seems to work, but only if I am accessing my peripheral with the same client.

    If I introduce a new client, then the whole bonding/pairing scenario for the new client doesn't appear to be functioning as I would expect, and my code jumps into attempting to grab the CTS info without bonding/pairing to the new client.  And this ultimately fails.

    Any ideas how I can check within my code whether my peripheral has paired/bonded with a specific client, and if not, set up a new pairing/bonding with that client?

    Cheers,

    Mike

  • OK, sorted it.  CONFIG_BT_MAX_PAIRED was set to 1.  Just increased that to 5 (I have 8192 bytes of flash storage for bonding/pairing info, so could potentially increase that a fair bit more) and I can get my peripheral to correctly grab the CTS from multiple clients now.

    I now want to ensure I don't end up hitting the limit of CONFIG_BT_MAX_PAIRED, so want to check the actual number of centrals paired at any given moment, and start removing earlier ones (or just wiping the whole lot clean) to keep below the limit.

    There appears to be a config setting CONFIG_BT_KEYS_OVERWRITE_OLDEST that if enabled, should allow the system to overwrite the oldest bonding/pairing info when it hits the CONFIG_BT_MAX_PAIRED limit. I can see a bunch of API's in keys.c that manage the overwriting, but its not clear how I get these to be implemented.  Is this something the code takes care of by simply setting CONFIG_BT_KEYS_OVERWRITE_OLDEST=y?  Or do I actually need to be calling those API's within my own code to manage the BT keys?

    I'm also trying to deal with the scenario where a central deletes the bonding information but this still remains within the peripheral.  At the moment, my code fails to work correctly if this happens, so I need someway of detecting this (I think its when I get a Reason 4 return from my pairing_failed() function.

    Cheers,

    Mike

  • Hi Mike, 

    Sorry for the late response. I haven't fully tested CONFIG_BT_KEYS_OVERWRITE_OLDEST but from what I can see in the code it seems that the oldest bond (most aged) will get removed automatically by bt_unpair() in keys.c : 
     

    Have you tried to test by just enabling CONFIG_BT_KEYS_OVERWRITE_OLDEST  ? 

    Regarding your question about having the central remove bond but the bond remains on the peripheral, it's about security requirement. There is a risk that an attacker can spoof that it's the central and request a new bond. So usually it's not allowed to request a new bond from a bonded central. 
    You will need to handle it with some extra security requirement, for example a physical button to erase all bonds (or single bond) , and you can call bt_unpair() in the code. In nRF5 SDK we have the allow_repair option, but I haven't seen the same option in Zephyr. 
    But it's possible to allow repair if it's JustWork pairing, you can use this config: CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE

Reply
  • Hi Mike, 

    Sorry for the late response. I haven't fully tested CONFIG_BT_KEYS_OVERWRITE_OLDEST but from what I can see in the code it seems that the oldest bond (most aged) will get removed automatically by bt_unpair() in keys.c : 
     

    Have you tried to test by just enabling CONFIG_BT_KEYS_OVERWRITE_OLDEST  ? 

    Regarding your question about having the central remove bond but the bond remains on the peripheral, it's about security requirement. There is a risk that an attacker can spoof that it's the central and request a new bond. So usually it's not allowed to request a new bond from a bonded central. 
    You will need to handle it with some extra security requirement, for example a physical button to erase all bonds (or single bond) , and you can call bt_unpair() in the code. In nRF5 SDK we have the allow_repair option, but I haven't seen the same option in Zephyr. 
    But it's possible to allow repair if it's JustWork pairing, you can use this config: CONFIG_BT_SMP_ALLOW_UNAUTH_OVERWRITE

Children
No Data
Related