cancel
Showing results for 
Search instead for 
Did you mean: 

How to enable and disable BLE privacy?

BStic.1
Associate II

In some modes I want to use a random static addresses (BLE privacy disabled) and in some modes I wand to use private resolvable addresses (BLE privacy enabled). The aci_gap_init function seems to force you to declare if BLE privacy is on or off. How do I switch this on and off? I get an error if I try to advertise with a random static address with BLE privacy enabled and vice versa.

6 REPLIES 6
Remi QUINTIN
ST Employee

To set the privacy level, the call to aci_gap_init fuction is mandatory at GAP level.

At the HCI level, it is still possible to use the hci_le_set_address_resolution_enable function to enable the privacy and it is possible to advertise with a private or random address calling the the hci_le_set_advertising_parameter function with own_address_type parameter set to 0x03 = resolvable private address or random.

I want to accomplish this:

  1. advertise without BLE privacy in the beginning to make it easy for a device to find my peripheral (if I enable privacy the device name is not advertised any more, which is the main reason for my desire to only use privacy mode when really necessary)
  2. use BLE privacy once the device is paired, so that the paired devices can still find each other

I'm aware that this requires different parameters when calling aci_gap_init. Now I'm confused as to how I'm allowed to *change* the mode after calling this function for step 1 with privacy NOT enabled. ONLY calling hci_le_set_address_resolution and hci_le_set_advertising_parameters doesn't work, I get error 0x42 when calling aci_gap_set_undirected_connectable or aci_gap_set_discoverable. May I simply call aci_gap_init again when I want to change the mode? If yes, under which circumstances is this allowed? If not, do I really have to reset CPU2 (I'm not aware of the possibility to simply shut it down) and start the complete initialization process anew just to change the privacy setting?

Remi QUINTIN
ST Employee

  1. Ok it’s the way to do it
  2. To use privacy: after pairing, bonding and disconnection, hci_reset is needed, gatt_init, aci_gap_init(privacy_enabled) add_device to resolving list and start advertising with private address. The advertizer can use its own private address that can be defined with own_address_type parameter. But to use it, a call to aci_gap_init(privacy_enabled) function must be performed.

Thanks, I will give this a try! In the meanwhile I tested privacy by manually switching the config on boot, and I'm experiencing problems on Android when writing to a writable characteristic and enabling notifications for a notifiable characteristic. (Android writes to STM32WB55 and tries to get notifications from it.)

I'm getting "GATT write not permitted" errors. Here is the setup code for those two characteristics.

// Data
COPY_DATA_UUID(uuid.Char_UUID_128);
aci_gatt_add_char(CustomContext.SvcHdle,
         UUID_TYPE_128, &uuid,
         SizeDat,
         CHAR_PROP_NOTIFY,
         ATTR_PERMISSION_NONE,
         GATT_NOTIFY_ATTRIBUTE_WRITE | GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP | GATT_NOTIFY_READ_REQ_AND_WAIT_FOR_APPL_RESP,
         0x10,
         CHAR_VALUE_LEN_VARIABLE,
         &(CustomContext.CustomDatHdle));
// Request
COPY_REQUEST_UUID(uuid.Char_UUID_128);
aci_gatt_add_char(CustomContext.SvcHdle,
         UUID_TYPE_128, &uuid,
         SizeReq,
         CHAR_PROP_WRITE_WITHOUT_RESP,
         ATTR_PERMISSION_AUTHEN_WRITE,
         GATT_NOTIFY_ATTRIBUTE_WRITE,
         0x10,
         CHAR_VALUE_LEN_VARIABLE,
         &(CustomContext.CustomReqHdle));

Both of those actions (enabling notifications and writing data) are working perfectly with Android if I don't use privacy, and both are working perfectly with iOS regardless of whether privacy is enabled or not!

Only Android together with privacy is problematic. (Android 9 if that's important.)

I'm achieving security level 3 or 4 in all of these scenarios, so I reckon that should be enough for ATTR_PERMISSION_AUTHEN_WRITE.

There must be something I'm missing, because I have this problem even with the nrf Connect Android app. I'm not getting any error events on the WB55 side, but I'm not getting the written data either.

Edit 1: I think I figured out what the issue is in the meantime, but not yet how I can solve it. I observed that the service and characteristic handles changed slightly when switching from normal mode to privacy mode.

Example logs from service/characteristic setup routines previously:

Manufacturer Name Characteristic Added Successfully  000D
Model Number String Characteristic Added Successfully  000F
Serial Number String Characteristic Added Successfully  0011
...

And now:

Manufacturer Name Characteristic Added Successfully  000F
Model Number String Characteristic Added Successfully  0011
Serial Number String Characteristic Added Successfully  0013
...

Android probably cached the previous handles and now simply uses the wrong addresses.

I verified this by reading the manufacturer name, model number, etc. using nrf Connect on Android, and every characteristic (except for the first one of course) returns the values from the characteristic that's below it in the list.

But I couldn't figure out how I can get a handle on the service changed characteristic to let Android know about this... I know that it's set up by aci_gatt_init, but other than aci_gap_init it does not provide the service/characteristic handles that were created back to me.

Edit 2: Nevermind, I found the handles of the service changed characteristic in PM0271 (rev. 4) pg. 27

DS.4
Senior II

Would like to achieve similar behavior, 

 

Does this issue have a better solution in latest stack?

 

Something that will not reque hci_reset and such?

Hi PHutf,
I don't know if you've seen this, but there's an example of BLE Privacy here that might help.
STM32WB-BLE-Privacy