In this exercise, we will start with a version of the Bluetooth Peripheral LBS sample that does not have any security support. This is similar to the application we created in Lesson 4 Exercises 1 and 2, where we created our own custom LED Button Service. All characteristics of the service are open and anyone can read and write to them without any encryption. This also means anyone with a sniffer can follow the connection and read the exchanged data.
We will start by adding the encryption requirement to a LED characteristic’s write permission. Then, we will add pairing support to the application and practice encrypting the link to be able to write to the LED characteristic.
The second part of the exercise focuses on increasing the security level to have man-in-the-middle protection, i.e security level 3 and 4. We will add a display callback to display the passkey in the log output so that we can see the passkey and enter the key to the phone. This way, the end user can ensure that they are pairing to the correct device.
In the GitHub repository for this course, go to the base code for this exercise, found in l5/l5_e1
of whichever version directory you are using.
This is a slightly modified version of the Peripheral LBS sample in nRF Connect SDK. lbs.c
and lbs.h
have been moved from the original SDK folder into the applications src
folder.
1. Add a security requirement to the LED characteristic
1.1 Change the LED characteristic permission to require encryption
In the declaration of the LED characteristic, add encryption requirement by changing BT_GATT_PERM_WRITE
to BT_GATT_PERM_WRITE_ENCRYPT
.
This will change the security level requirement from level 1 (no security) to level 2 (unauthenticated encryption) as covered in Security Models topic earlier.
Change the following code in lbs.c
BT_GATT_CHARACTERISTIC(BT_UUID_LBS_LED,
BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE_ENCRYPT,
NULL, write_led, NULL),
C2. Build and flash the application to the board.
3. Try to write to the LED characteristic.
In nRF Connect for Mobile, connect to the device Nordic_LBS
. Try to write to the LED characteristic to turn it on, as we have done in previous exercises. Notice that the LED3 (LED2 on nRF54L15 DK) on the board does not react. This is because the characteristic now requires encryption, but the firmware does not have pairing support. The phone may terminate the connection because of this.
Let’s add pairing support to the firmware.
4. Add the Security Management Protocol layer to the Bluetooth LE stack.
The Kconfig symbol CONFIG_BT_SMP
will add the Security manager Protocol to the Bluetooth LE stack, which is the layer that makes it possible to pair devices over Bluetooth LE.
Add the following line to the prj.conf
file
CONFIG_BT_SMP=y
Kconfig5. Add a callback function for when the security level of the connection has changed.
Recall the connection callback structure struct bt_conn_cb
that we used in the previous exercises. Let’s add a callback for the security_changed
event as well.
5.1 Add the security_changed
member to the callback structure
Add the following line in main.c
.security_changed = on_security_changed,
C5.2 Define the callback function on_security_changed()
.
We want this callback function to display the current security level of the connection and inform if the link has been encrypted successfully or not.
Add the following code in main.c
static void on_security_changed(struct bt_conn *conn, bt_security_t level,
enum bt_security_err err)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
if (!err) {
LOG_INF("Security changed: %s level %u\n", addr, level);
} else {
LOG_INF("Security failed: %s level %u err %d\n", addr, level,
err);
}
}
C6. Build and flash the application to the board.
Open up a terminal to see the log output from the application, which we will need to get the passkey.
Just like in previous exercises, you can go to Visual Studio Code and select the COM port for the device.
7. Try to write to the LED characteristic.
In nRF Connect for Mobile, connect to the device Nordic_LBS
. Try to write to the LED characteristic to turn it on.
Now verify that a pairing pop-up Window appears after you select Write.
Select Pair to accept the pairing and the LED characteristic should now be possible to control. The Bluetooth LE link is now encrypted.
In the log, you should see the security level updated to level 2 in the UART log:
*** Booting nRF Connect SDK 2.6.1-3758bcbfa5cd ***
Starting Lesson 5 - Exercise 1
Bluetooth initialized
Advertising successfully started
Connected
Security changed 7B:9E:28:DB:38:7A (random) level 2
Terminal8. Change the LED characteristic permission to require pairing with authentication
In the declaration of the LED characteristic, add the authentication requirement by changing
to BT_GATT_PERM_WRITE_ENCRYPT
BT_GATT_PERM_WRITE_AUTHEN
.
Change the following code in lbs.c
BT_GATT_CHARACTERISTIC(BT_UUID_LBS_LED,
BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE_AUTHEN,
NULL, write_led, NULL),
CThis will increase the security level of the write permission of this characteristic from level 2 to level 3 or 4, depending in whether you are using legacy pairing or LE Secure Connections.
At this stage, even though you would still be able to pair with the board, the phone wouldn’t be able to control the LED. This is because the security level of the application doesn’t meet the requirement of the characteristic permission.
9. Define authentication callback functions
We have the authenticated pairing callback structure struct bt_conn_auth_cb
with numerous members. In our case, we will only add two.
9.1 Define the callback function auth_passkey_display
Let’s define a function for the passkey_display
event, which has the following signature
This will print the passkey needed for the central (your phone) to pair with the peripheral (the board).
Add the following code in main.c
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Passkey for %s: %06u\n", addr, passkey);
}
C9.2 Define the callback function auth_cancel
Let’s define a function for the cancel
event, which has the following signature
This will let us know when the pairing has been cancelled.
Add the following code in main.c
static void auth_cancel(struct bt_conn *conn)
{
char addr[BT_ADDR_LE_STR_LEN];
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
LOG_INF("Pairing cancelled: %s\n", addr);
}
C9.3 Declare the authenticated pairing callback structure struct bt_conn_auth_cb
.
Let’s now declare the callback structure with the two member functions that we created in the previous steps.
Add the following code to main.c
static struct bt_conn_auth_cb conn_auth_callbacks = {
.passkey_display = auth_passkey_display,
.cancel = auth_cancel,
};
C10. Register the authentication callbacks.
Add the following code in main.c
err = bt_conn_auth_cb_register(&conn_auth_callbacks);
if (err) {
LOG_INF("Failed to register authorization callbacks.\n");
return -1;
}
CThe application now fulfills the requirements of pairing with MITM authentication needed for security level 3 or level 4.
11. Build and flash the application on the board.
11.1 Make sure you select Erase And Flash To Board, to remove the previous bonding information.
11.2 Remove the bond information from your phone.
On the phone, you would need to remove the bond information of the device as well.
Go to your Bluetooth settings, find the device and select the pin wheel next to it. Then select Unpair.
Go to your Bluetooth settings, find the device and select the information icon next to it. Then select Forget This Device.
12. Use your phone to connect the device and prompt the pairing request by writing to the LED characteristic.
As we have done previously, use nRF Connect for Mobile to connect to the device. Then try to write to the LED characteristic and the pairing pop-up window should appear, now with a PIN request.
The passkey, a 6-digit randomly generated number, will be in the log output from the device. You will need to type this passkey to the pop-up window on the phone.
In the log output below, the passkey is 043166.
*** Booting nRF Connect SDK 2.6.1-3758bcbfa5cd ***
Starting Lesson 5 - Exercise 1
Bluetooth initialized
Advertising successfully started
Connected
Passkey for 48:18:67:01:CC:A8 (random): 043166
TerminalIf you enter the passkey correctly, the phone and the device will pair successfully and you will be able to control the LED.
Verify in the log output that you now have security level 3 (for legacy pairing) or 4 (for LE Secure Connections).
Connected
Passkey for 48:18:67:01:CC:A8 (random): 043166
Security changed 48:18:67:01:CC:A8 (random) level 4
Terminal