GAP Bond Manager and LE Secure Connections¶
The GAP Bond Manager (GAPBondMgr) is a configurable module that offloads most of the Pairing & Bonding security mechanisms associated with the Security Manager (SM) protocol from the application. The GAPBongMgr executes in the protocol stack task’s context. Table 1. lists the terminology.
Term | Description |
Pairing | The process of generating & exchanging keys. Not to be confused with forming or establishing a BLE connection between two devices |
Encryption | Data is encrypted after pairing, or re-encryption (a subsequent connection where keys are looked up from nonvolatile memory). |
Association | The pairing method used based on the I/O Capabilities of both devices. For LE devices, Just Works, Numeric Comparison, Passkey Entry and Out-Of-Band are supported. |
Authentication | The pairing process using an association method that supports MITM (Man in the Middle) protection. |
Bonding | Storing the keys generated during the pairing process in nonvolatile memory to use for the next encryption sequence. |
Authorization | An additional application level verification in addition to authentication. |
OOB | Out of Band. Pairing keys are not exchanged over the air, but rather over some other source such as serial port or NFC. This also provides MITM protection. |
MITM | Man in the Middle protection. MITM provides authentication during the pairing process which helps prevent a malicious attacker from impersonating the peer device during the key exchange. |
Just Works | Unauthenticated pairing association method where keys are exchanged without MITM protection. |
The general process that the GAPBondMgr uses is as follows:
1. The pairing process: exchange keys through the methods described in Selection of Pairing Method.
- The encryption process: Encrypt the link using keys Step 1.
3. The bonding process: store keys in secure flash (Simple Non Volatile memory, SNV).
- Reconnecting: Use the keys stored in SNV to encrypt the link.
Tip
Performing all of these steps is not necessary. For example, two devices may choose to pair but not bond.
Selection of Pairing Method¶
Bluetooth Core Specification Version 4.2 added support for the LE Secure Connections feature to enable additional strength to the BLE pairing process. For a detailed description of the algorithms used for LE Secure Connections, see the Security Architecture section ([Vol 1], Part A, Section 5.1) of the Bluetooth Core Specification Version 5.0. The previous pairing methods used in the Bluetooth Core Specification Versions 4.1 and 4.0 are still available, and are now defined as LE Legacy Pairing. The main difference is that Secure Connection uses Elliptic Curve Diffie-Hellman (ECDH) cryptography, while LE Legacy Pairing does not.
There are four types of pairing methods which are referred to as “Association Models” in the core specification. Each pairing method is described in detail in GAPBondMgr Examples for Different Pairing Methods.
- Just Works (LE Secure Connections or LE Legacy)
- Passkey Entry (LE Secure Connections or LE Legacy)
- Numeric Comparison (LE Secure Connections)
- Out Of Band (LE Secure Connections or LE Legacy)
Which pairing method is selected, and whether or not pairing will succeed depends on the following parameters from both peer devices during the pairing process:
- Out Of Band (OOB) set / not set
- Man In The Middle (MITM) set / not set
- Input/Output (IO) Capabilities
- LE Secure Connections supported / not supported
The GAPBondMgr parameters, as they map to the table parameters below are listed here. For more information on these parameters, see BLE Stack API Reference (GAPBondMgr section).
GAPBOND_OOB_ENABLED: Out of band (OOB) set / not set
GAPBOND_MITM_PROTECTION: Man in the middle (MITM) set / not set
GAPBOND_IO_CAPABILITIES: Input/Output (IO) Capabilities
GAPBOND_SECURE_CONNECTION: LE Secure connections supported / not supported
Beyond what the Bluetooth Core Specification Version 5.0 defines, this parameter also affects whether or not pairing succeeds, as described in BLE Stack API Reference (GAPBondMgr section).
The tables below are from the Selecting Key Generation Method section ([Vol 3], Part H, Section 2.3.5.1) of the Bluetooth Core Specification Version 5.0. Use these tables to determine which pairing mode is selected for any set of parameters.
If both devices support LE Secure Connections, use Figure 27. to decide upon the next step.
If at least one device does not support LE Secure Connections, use Figure 28. to decide upon the next step.
If, based on one of the previous tables, IO capabilities are to be used to determine the association model, use Figure 29.
Using GAPBondMgr¶
This section describes what the application must do to configure, start, and use
the GAPBondMgr. The GAPBondMgr is defined in gapbondmgr.c
and gapbondmgr.h
.
BLE Stack API Reference (GAPBondMgr section) describes the full API including
commands, configurable parameters, events, and callbacks.
The general steps to use the GAPBondMgr module are as follows:
1. Configure the stack to include GAPBondMgr functionality by defining the
following in build_config.opt
in the stack project:
-DGAP_BOND_MGR
2. The stack must also be configured to use 1 or 2 SNV pages, by
defining OSAL_SNV=1
or OSAL_SNV=2
as a preprocessor-defined symbol in
the stack project.
3. If using LE Secure Connections, the PDU size must be >= 69. This can be set by
defining the following preprocessor symbol in the application
project: MAX_PDU_SIZE=69
. Also, the minimum heap size that can be used with
LE Secure Connections is 3690. (See Dynamic Memory Allocation for heap size
management.)
4. Configure the GAPBondMgr by initializing its parameters as desired. GAPBondMgr configuration parameters are not persistent and must be configured after the device is reset. See BLE Stack API Reference (GAPBondMgr section) for a complete list of parameters with functionality described. There are examples of this for the various pairing/bonding modes in GAPBondMgr Examples for Different Pairing Methods.
5. Register application callbacks with the GAPBondMgr, so that the application can communicate with the GAPBondMgr and be notified of events.
// Register with bond manager after starting device GAPBondMgr_Register(&bondmanager_callbacks);
Here bondmanager_callbacks
is defined as a structure containing the
GAPBondMgr Callbacks. A passcode callback function is mandatory.
// Bond Manager Callbacks static gapBondCBs_t bondMgrCBs = { SimpleCentral_passcodeCb, // Passcode callback SimpleCentral_pairStateCb // Pairing/Bonding state Callback };
6. Once the GAPBondMgr is configured, it operates mostly autonomously from the perspective of the application. When a connection is established, the GAPBondMgr manages pairing and bonding depending on the configuration parameters set during initialization. It also communicates with the application as needed through the defined callbacks.
A few parameters can be set and functions can be called asynchronously at any time from the application. See BLE Stack API Reference (GAPBondMgr section) for more information.
Most communication between the GAPBondMgr and the application at this point occurs through the callbacks which were registered in Step 5. Figure 30. is a flow diagram example of the GAPBondMgr notifying the application that pairing has been completed. The same method occurs for various other events and will be expanded upon in the following section.
GAPBondMgr Examples for Different Pairing Methods¶
This section provides message diagrams for the types of security that can be implemented. These modes assume acceptable I/O capabilities are available for the security mode, and that the selection of whether or not to support LE Secure Connections allows for the pairing method. See the Selection of Pairing Method on how these parameters affect pairing. These examples only consider the pairing aspect. Bonding can be added to each type of pairing in the same manner and is shown in the next section.
Caution
The code snippets here are not complete functioning examples, and are only intended for illustration purposes.
Disabling Pairing¶
With pairing mode set to GAPBOND_PAIRING_MODE_NO_PAIRING
, the BLE stack
automatically rejects any attempt at pairing.
Configure the GAPBondMgr as follows to disable pairing:
// Pairing is not allowed
uint8_t pairMode = GAPBOND_PAIRING_MODE_NO_PAIRING;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
Enabling Pairing¶
To start or allow the pairing process after a connection is formed, the GAPBondMgr can be
configured to automatically request pairing or wait for pairing request from the
peer device. The actual behavior depends on the device’s GAP role (Central or Peripheral)
and the setting of the GAPBondMgr pairing mode (GAPBOND_PAIRING_MODE
).
To initiate the pairing process on Peripheral role devices, GAPBOND_PAIRING_MODE_INITIATE
will
send a Slave Security Request shortly after the GAPBondMgr is informed that the connection is formed.
For Central role devices, GAPBOND_PAIRING_MODE_INITIATE
will send a Pairing Request or request
the Link Layer to encrypt the link if the device has previously paired/bonded:
// Initiate pairing request
uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
The Peripheral can be configured to wait for a Pairing Request from the Central when the pairing mode
is set to GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
. When this pairing mode is selected, the GAPBondMgr will
automatically respond with a Pairing Response based on other GAPBondMgr configured parameters.
// Wait for a pairing request
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
Tip
When pairing with smartphone Central devices, it is recommended to use GAPBOND_PAIRING_MODE_WAIT_FOR_REQ
as undefined behavior may occur when a Slave Security Request is sent by the Peripheral. Both iOS
and Android will initiate pairing when the peripheral responds with an Insufficient Authentication error
response when a GATT secure characteristic is accessed.
LE Secure Connections¶
LE Secure Connections is enabled by default in BLE5-Stack. If you don’t want to use
LE Secure Connections, set the GAPBOND_SECURE_CONNECTION
variable
to GAPBOND_SECURE_CONNECTION_NONE
during the GAPBondMgr initialization.
uint8_t gapbondSecure = GAPBOND_SECURE_CONNECTION_NONE;
GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &gapbondSecure);
It is important when trying to decipher over-the-air sniffer logs with LE Secure
Connections enabled, you need to use a specific “debug” key as defined by Vol 3
Part H section 2.3.5.6.1 of the Bluetooth Core Specification Version 5.0. In the BLE5-Stack, this key is
enabled when the GAPBondMgr has SC_HOST_DEBUG
defined in the stack project.
When either the initiating or non-initiating device uses this specific debug
key, it enables over-the-air sniffer equipment that supports LE Secure Connections to
determine the LTK and therefore monitor/decrypt encrypted traffic throughout
the connection.
Just Works Pairing¶
Just Works pairing allows encryption without man in the middle (MITM) authentication and is vulnerable to MITM attacks. Just Works pairing can be LE Legacy or LE Secure Connections pairing. The GAPBondMgr does not need any additional input from the application for Just Works pairing. Configure the GAPBondMgr for Just Works pairing as follows.
uint8_t mitm = FALSE;
GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof (uint8_t), &mitm);
Figure 31. describes the interaction between the GAPBondMgr and
the application for Just Works pairing. As shown, the application receives
a GAPBOND_PAIRING_STATE_STARTED
event once the pairing request has been sent,
and a GAPBOND_PAIRING_STATE_COMPLETE
event once the pairing process has been
completed. At this time, the link is encrypted.
Passcode Entry¶
Passkey entry is a type of authenticated pairing that can prevent man in the middle (MITM) attacks. It can be used with either LE Legacy pairing or Secure Connections pairing. In this pairing method, one device displays a 6-digit passcode, and the other device enters the passcode. As described in Selection of Pairing Method, the IO capabilities decide which device performs which role. The passcode callback registered with the GAPBondMgr when it was started is used to enter or display the passcode. The following is an example of initiating Passcode Entry pairing where the passcode is displayed.
- Define passcode callback
// Bond Manager Callbacks
static gapBondCBs_t bondMgrCBs =
{
SimpleCentral_passcodeCb, // Passcode callback
SimpleCentral_pairStateCb // Pairing/Bonding state Callback
};
/*********************************************************************
* @fn SimpleCentral_passcodeCb
*
* @brief Passcode callback.
*
* @return none
*/
static void SimpleCentral_passcodeCb(uint8_t *deviceAddr, uint16_t connHandle,
uint8_t uiInputs, uint8_t uiOutputs,
uint32_t numComparison)
{
uint8_t *pData;
// Allocate space for the passcode event.
if ((pData = ICall_malloc(sizeof(uint8_t))))
{
*pData = uiOutputs;
// Enqueue the event.
SimpleCentral_enqueueMsg(SC_EVT_PASSCODE_NEEDED, 0, pData);
}
}
- Configure GAPBondMgr
uint8_t pairMode = GAPBOND_PAIRING_MODE_INITIATE;
uint8_t mitm = TRUE;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
- Process passcode callback and send the response to the stack.
//! BLE Default Passcode
#define B_APP_DEFAULT_PASSCODE 123456
/*********************************************************************
* @fn SimpleCentral_processPasscode
*
* @brief Process the Passcode request.
*
* @return none
*/
static void SimpleCentral_processPasscode(uint16_t connHandle,
uint8_t uiOutputs)
{
// Display passcode to user
if (uiOutputs != 0)
{
Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Passcode: %d",
B_APP_DEFAULT_PASSCODE);
}
// Send passcode response
GAPBondMgr_PasscodeRsp(connHandle , SUCCESS, B_APP_DEFAULT_PASSCODE);
}
Depending on the uiInputs
and uiOutputs
returned from the GAPBondMgr,
the passcode must either be displayed or entered. The passcode is
then sent to the GAPBondMgr using GAPBondMgr_PasscodeRsp(), so that
pairing can continue. In this case, the password is statically set to 123456.
In a real product, the password will likely be randomly generated, and the
device must expose a way for the user to enter the passcode, then send it to the
GAPBondMgr using GAPBondMgr_PasscodeRsp(). An example interaction
between the GAPBondMgr and the application is shown in
Figure 32..
Numeric Comparison¶
Numeric comparison is a type of authenticated pairing that protects from MITM attacks. It is only possible as a LE Secure Connections pairing; not LE legacy. For numeric comparison pairing, both devices display a 6-digit code. Each device must then indicate, through a button press or some other Yes-No input, whether the codes match. The passcode callback registered with the GAPBondMgr when it was started is used to display the 6-digit code. The following is an example of initiating Numeric Comparison pairing where the passcode is displayed. The IO capabilities must be set appropriately to select numeric comparison (that is, Display/Yes-No on both sides).
- Define passcode callback to display code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Bond Manager Callbacks
static gapBondCBs_t bondMgrCBs =
{
SimpleCentral_passcodeCb, // Passcode callback
SimpleCentral_pairStateCb // Pairing/Bonding state Callback
};
static void SimpleCentral_passcodeCb(uint8_t *deviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs, uint32_t numComparison)
{
gapPasskeyNeededEvent_t *pData;
// Allocate space for the passcode event.
if ((pData = ICall_malloc(sizeof(gapPasskeyNeededEvent_t))))
{
memcpy(pData->deviceAddr, deviceAddr, B_ADDR_LEN);
pData->connectionHandle = connHandle;
pData->numComparison = numComparison;
// Enqueue the event.
SimpleCentral_enqueueMsg(SC_EVT_PASSCODE_NEEDED, 0, pData);
|
- Configure GAPBondMgr
1 2 3 4 5 6 7 8 9 | uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
uint8_t scMode = GAPBOND_SECURE_CONNECTION_ONLY;
uint8_t mitm = TRUE;
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_YES_NO;
GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_SECURE_CONNECTION, sizeof(uint8_t), &scMode);
|
- Process passcode callback and display code.
1 2 3 4 5 6 7 8 9 10 11 12 13 | static void SimpleCentral_processPasscode(uint16_t connHandle,
uint8_t uiOutputs)
{
// Display passcode to user
if (uiOutputs != 0)
{
Display_printf(dispHandle, SC_ROW_CUR_CONN, 0, "Passcode: %d",
B_APP_DEFAULT_PASSCODE);
}
// Send passcode response
GAPBondMgr_PasscodeRsp(connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE);
}
|
- Accept Yes-No input from user and send response to GAPBondMgr.
1 2 3 4 5 6 | if (keys & KEY_RIGHT)
{
//Send response to indicate that code matches
GAPBondMgr_PasscodeRsp(connHandle, SUCCESS, TRUE);
return;
}
|
In this case, the third parameter of GAPBondMgr_PasscodeRsp, which usually accepts a passcode, is overloaded to send TRUE to the stack to indicate that the codes match and to continue with pairing. The process of numeric comparison is illustrated in Figure 33.
GAPBondMgr Example With Bonding Enabled¶
Bonding can enabled or disabled for any type of pairing through the
GAPBOND_BONDING_ENABLED
parameter, and occurs after the pairing
process is complete. To enable bonding, configure the GAPBondMgr as
follows:
uint8_t bonding = TRUE;
GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
With bonding enabled, the GAPBondMgr stores the long-term key
transferred during the pairing process to SNV. See GAPBondMgr and SNV for more information. After this is completed, the application is notified
through the GAPBOND_PAIRING_STATE_COMPLETE
event. GAPBOND_PAIRING_STATE_BOND_SAVED
is only passed to the application pair
state callback when initially connecting, pairing, and bonding. For
future connections to a bonded device, the security keys are loaded from
flash, thus skipping the pairing process. In this case, only
GAPBOND_PAIRING_STATE_BONDED
is passed to the application pair state callback. This is illustrated in Figure 34.
GAPBondMgr and SNV¶
This section describes how the GAPBondMgr uses the SNV flash area
for storing bonding information. For more information on SNV itself,
see Flash. The amount of bonds that can be stored
is set by the GAP_BONDINGS_MAX
definition, which is set to 10 by default in
gapbondmgr.h, which can be modified as needed by the application.
The functionality of the GAPBondMgr when there are no
more available bonds varies based on whether the “least recently
used” scheme is enabled. See BLE Stack API Reference (GAPBondMgr section) for
more information
on the GAPBOND_LRU_BOND_REPLACEMENT
parameter. If this parameter is set
to false, it is not possible to add any more bonds without manually
deleting a bond. If the parameter is set to true, the least recently
used bond is deleted to make room for the new bond.
The following components comprise one bonding entry:
- Bond Record: this consists of the peer’s address, address type, privacy reconnection address, and state flags. This comprises 13 bytes and is defined as such:
// Structure of NV data for the connected device's address information
typedef struct
{
/**
* Peer's address
*
* If identity information exists for this bond, this will be an
* identity address
*/
uint8_t addr[B_ADDR_LEN];
/**
* Peer's address type
*/
GAP_Peer_Addr_Types_t addrType;
/**
* State flags of bond
*
* @ref GAP_BONDED_STATE_FLAGS
*/
uint8_t stateFlags;
} gapBondRec_t;
- Client Characteristic Configurations (CCC): the amount of CCCs stored
in each entry are set by the
GAP_CHAR_CFG_MAX
define. This is set to 4 by default. Each CCC is comprised of 4-bytes and is defined as follows:
// Structure of NV data for the connected device's characteristic configuration
typedef struct
{
uint16 attrHandle; // attribute handle
uint8 value; // attribute value for this device
} gapBondCharCfg_t;
- Local Long Term Key (LTK) info: this stores the local device’s encryption information. This comprises 28 bytes and is composed as such:
typedef struct
{
uint8 LTK[KEYLEN]; // Long Term Key (LTK)
uint16 div; //lint -e754 // LTK eDiv
uint8 rand[B_RANDOM_NUM_SIZE]; // LTK random number
uint8 keySize; // LTK key size
} gapBondLTK_t;
- Connected Device Long Term Key Info: this stores the connected device’s encryption information. This is also a gapBondLTK_t and comprises 28 bytes.
- Connected Device Identity Resolving Key (IRK): this stores the IRK generated during pairing. This is a 16-byte array.
- Connected Device Sign Resolving Key (SRK): this stores the SRK generated during pairing. This is a 16-byte array.
- Connected Device Sign counter: this stores the sign counter generated during pairing. This is a 4-byte word.
Privacy¶
BLE5-Stack supports the Controller-based privacy variant as defined by the Bluetooth Core Specification Version 5.0 (Vol 1, Part A, Section 5.4.5) and is always compiled into the BLE5-Stack libraries. The privacy feature greatly reduces the ability for a scanner to track broadcasting Bluetooth low energy devices over a period of time. This is accomplished by allowing devices to frequently change their addresses (Default timeout value is every 15 minutes).
Privacy is discussed in the following sections of the Bluetooth Core Specification Version 5.0. It is suggested to review and familiarize yourself with these sections before continuing.
- Vol 6, Part B, Section 6 - Privacy in the Link Layer
The following terms are used throughout the Privacy section. It’s suggested to review these terms before continuing.
The privacy feature is largely implemented in the Link Layer of the Controller, however it requires interaction with the Host to manage communication with other devices using privacy. As described in the Bluetooth Core Specification Version 5.0 (Vol 1, Park A, Section 5.4.5), there are two modes of privacy: device privacy mode and network privacy mode:
In Device Privacy Mode, a local device is only concerned with its own privacy. This means that it will accept advertising/scan/connection packets from peer devices that use their Identity Address (IA) or a Resolvable Private Address (RPA) even if both devices have distributed their Identity Resolving Keys (IRK) with one another. A local device may use this mode with a peer device if the peer device does not have the Resolvable Private Address Only (RPAO) GATT characteristic.
In Network Privacy Mode, a local device respects the privacy of a bonded peer device. If both devices have distributed their Identity Resolving Keys (IRK), the local device shall only accept advertising/scan/connection packets from the peer device’s Resolvable Private Address. In Bluetooth Core Specification Version 5.0, Network Privacy Mode is the default privacy mode.
Resolvable Private Addresses¶
A Resolvable Private Address (RPA) is a device address that is generated using an Identity Resolving Key (IRK). This key is exchanged during Phase 3 of the bonding procedure along with the peer device’s Identity Address. From this point on, given that a peer has a valid IRK and supplies a Resolvable Private Address, the peer device can resolve this RPA into the associated Identity Address. The Resolvable Private Address of a peer device not used at the Host layer of the local device after the IRK exchange. Instead, the RPA is resolved in the Controller and the Host is only given the associated peer’s Identity Address.
A BLE5-Stack application configures the device address type it uses with the
addrMode
parameter of GAP_DeviceInit(). This API must be called
after the GAP layer has been initialized and before attempting to start
discovery or advertising. See Listing 77..
static void SimplePeripheral_init(void)
{
...
//Initialize GAP layer for Peripheral role and register to receive GAP events
GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, selfEntity, ADDRMODE_RP_WITH_PUBLIC_ID, NULL);
...
Resolvable Private Address Timeout¶
When using an RPA, the Bluetooth Core Specification Version 5.0 specifies a default timeout interval of 15 minutes before the device changes its device address. This can be changed via the GAP_PARAM_PRIVATE_ADDR_INT parameter in GAP_SetParamValue().
static void SimplePeripheral_init(void)
{
...
// Configure GAP
{
uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION;
uint16_t rpaTimeoutInterval = 5;
// Pass all parameter update requests to the app for it to decide
GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, ¶mUpdateDecision);
GAP_SetParamValue(GAP_PARAM_PRIVATE_ADDR_INT, &rpaTimeoutInterval);
}
...
}
Resolving List¶
The privacy feature inhibits tracking from untrusted peer devices. However, some devices may need the ability to recognize its peer devices over time. In order to do this, the devices perform an IRK exchange during the bonding process described above. Once bonded with a peer device, if the local device receives incoming Link Layer events from the peer device that is using a Resolvable Private Address, then the local device will try to resolve this address into an Identity Address. To do so, each device’s link layer maintains a Bluetooth Core Specification Version 5.0 defined table known as a Resolving List. Upon reset, the Resolving List is empty and it’s up to the host to add and remove devices from the Resolving List. This is automatically handled for the application when using the GAPBondMgr.
A resolving list record entry consists of the following:
- an Identity Address
- the address type of Identity Address (Public or Random Static)
- the IRK used to resolve the Identity Address
- which Privacy mode the device is in (Network or Device)
In the case in which a local device receive a link layer event from a peer device that used a Resolvable Private Address which is not in the Resolving List, then the link layer may pass such link events to the host for further resolution (if permitted by the White List).
Note
Many mobile devices use a Resolvable Private Address when initiating a connection to a device that it has never previously bonded with. Since the advertiser doesn’t have a valid IRK stored in its Resolving List, the advertiser cannot resolve the device address and it will defer to the Host for further action.
In the event the peer IRK is no longer valid, one of the GAPBOND_ERASE parameters can be used to erase the bond record and remove the entry from the Resolving List.
White List¶
The Host also has the option to configure a filter policy in a White List which is also in the Controller’s link layer. When enabled, policies can be set to filter out Link Layer events after they were processed by the Resolving List. This provides an additional filter if you only want to communicate with certain devices you have bonded with at a time. The Host can update the devices in the White List so that the Controller can automatically process future connection or scan events.
The intent for the White List mechanism is to reduce power consumption.
By removing undesirable Link Layer events at the Controller, the Host can
remain in low power modes. In order to take advantage of white list filtering,
set the appropriate GapAdv
and GapScan
filter policies as
described in the BLE5-Stack API Guide.
The GAPBondMgr can also be configured to have bonded device automatically added to the Controller’s White List by setting the GAPBOND_AUTO_SYNC_WL parameter.
Network Privacy Mode vs. Device Privacy Mode¶
A device can interact with a peer device exclusively in Network Privacy Mode or exclusively Device Privacy Mode, not both. The mode is determined during Phase 3 of the bonding procedure. This is automatically handled for the application when using the GAPBondMgr. After the devices exchange each others’ IRK, each local device will try to read peer’s Resolvable Private Address Only characteristic via a GATT_ReadUsingCharUUID(). If a GATT_MSG_EVENT with a ATT_READ_BY_TYPE_RSP is generated, then the local device understands that the peer device is in Network Privacy mode. However, if a GATT_MSG_EVENT response with a ATT_ERROR_RSP is generated, then the local device will interact with the device in Device Privacy Mode.
In Device Privacy Mode, a local device is only concerned in protecting its own privacy once the device has a valid bond with a peer device. After a peer and local device have bonded, a local device can accept (given that white list filter policy allows it) connections with a peer using a Resolvable Private Address or its Identity Address as its device address.
In Bluetooth Core Specification Version 5.0, Network Privacy Mode has been added. In this mode, a device is concerned to respect the the privacy of peer. After a peer and local device have bonded, a local device will only accept (given that white list filter policy allow) connections with a peer device if it uses a Resolvable Private Address as its device address.
For BLE5-Stack project to use Network Privacy Mode, the GAPBondMgr
requires the stack’s GATT client to read the peer device’s
Resolvable Private Address Only characteristic. In order to accomplish
this, the stack must be built with GATT_NO_CLIENT
compiler option disabled
so that the GATT client is included.
Using Privacy in BLE5-Stack¶
1. Enable the GATT client.
The application must have the GATT client to read the Resolvable Private Address Only characteristic. IfGATT_NO_CLIENT
is defined in the project’s predefined symbols, remove it. See Compiler Options on how to change predefined project symbols.
2. Configure device to use Resolvable Private Addresses.
Modify GAP_DeviceInit() as highlighted in Listing 77. to use a Resolvable Private Address.
Optionally, add the code snippet highlighted in Listing 78. to change the timeout interval in which the controller changes its Resolvable Private Address.
- 3. Enable bonding to share your identity with trusted peer devices.
GAPBOND_BONDING_ENABLED
is a GAP Bond Manager Parameter that allows you to bond with a peer device during the pairing process. During this process, the devices share their IRKs so they can be known in the future when their RPAs change.