Skip to content

Commit

Permalink
applications: Added BT security support for the Matter bridge
Browse files Browse the repository at this point in the history
Extended the Matter bridge BLE connectivity manager by the
support for BT SMP and allowing to establish secure connections
with the Bluetooth LE bridged devices.

Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no>
  • Loading branch information
kkasperczyk-no authored and rlubos committed Jan 11, 2024
1 parent b12eae1 commit f84125d
Show file tree
Hide file tree
Showing 13 changed files with 396 additions and 19 deletions.
24 changes: 24 additions & 0 deletions applications/matter_bridge/Kconfig
Expand Up @@ -98,6 +98,30 @@ config BT_GATT_CLIENT
config BT_GATT_DM
default y

config BT_SMP
default y

if BT_SMP

config BT_SETTINGS
default y

# Configure how many Bluetooth LE devices will be paired with Matter bridge. Assuming it will be only bridged devices, it should be set to BT_MAX_CONN - 1.
config BT_MAX_PAIRED
default 2

# Use two Bluetooth LE identities. The first one is used by the peripheral for Matter service advertising purposes, and the other is used by the Matter bridge central.
config BT_ID_MAX
default 2

config BT_EXT_ADV
default y

config BT_EXT_ADV_LEGACY_SUPPORT
default y

endif

config BRIDGE_BLE_DEVICE_POLLING_INTERVAL
int "BLE humidity measurement readout polling interval in ms"
default 3000
Expand Down
1 change: 1 addition & 0 deletions applications/matter_bridge/child_image/hci_ipc/prj.conf
Expand Up @@ -17,3 +17,4 @@ CONFIG_RESET_ON_FATAL_ERROR=n

CONFIG_BT_MAX_CONN=10
CONFIG_BT_CENTRAL=y
CONFIG_BT_EXT_ADV=y
Expand Up @@ -17,3 +17,4 @@ CONFIG_RESET_ON_FATAL_ERROR=y

CONFIG_BT_MAX_CONN=10
CONFIG_BT_CENTRAL=y
CONFIG_BT_EXT_ADV=y
107 changes: 106 additions & 1 deletion applications/matter_bridge/doc/matter_bridge_description.rst
Expand Up @@ -280,12 +280,46 @@ Adding a Bluetooth LE bridged device to the Matter bridge

.. code-block:: console
---------------------------------------------------------------------
| Bridged Bluetooth LE device authentication |
| |
| Insert pin code displayed by the Bluetooth LE peripheral device |
| to authenticate the pairing operation. |
| |
| To do that, use matter_bridge pincode <pincode> shell command. |
---------------------------------------------------------------------
To complete the adding process, you must use the ``pincode`` command to insert the authentication pincode displayed by the bridged device.

Inserting a Bluetooth LE authentication pincode
Use the following command:

.. parsed-literal::
:class: highlight
matter_bridge pincode *<ble_pincode>*
In this command, *<ble_pincode>* is the Bluetooth LE authentication pincode of the bridged device to be paired.

Example command:

.. code-block:: console
uart:~$ matter_bridge pincode 305051
The terminal output is similar to the following one:

.. code-block:: console
I: Pairing completed: E3:9D:5E:51:AD:14 (random), bonded: 1
I: Security changed: level 4
I: The GATT discovery completed
I: Added device to dynamic endpoint 3 (index=0)
I: Added device to dynamic endpoint 4 (index=1)
I: Created 0x100 device type on the endpoint 3
I: Created 0xf device type on the endpoint 4
Removing a bridged device from the Matter bridge
Use the following command:

Expand Down Expand Up @@ -353,6 +387,33 @@ Build the target using the following command in the project directory to enable
Replace *absolute_path* with the absolute path to the Matter bridge application on your local disk.

Configuring the Bluetooth LE security
-------------------------------------

The application uses Bluetooth LE Security Manager Protocol (SMP) to provide secure connection between the Matter bridge and Bluetooth LE bridged devices.

.. note::
Do not confuse the Bluetooth LE Security Manager Protocol (SMP) abbreviation with the Bluetooth LE Simple Management Protocol that has the same abbreviation and is used for the Device Firmware Upgrade process.

The following security levels are defined by the Bluetooth LE specification:

* Security Level 1 - supports communication without security.
* Security Level 2 - supports AES-CMAC communication encryption, but does not require device authentication.
* Security Level 3 - supports AES-CMAC communication encryption, requires device authentication and pairing.
* Security Level 4 - supports ECDHE communication encryption, requires authentication and pairing.

To read more about the Bluetooth LE security implementation in Zephyr, see the Security section of the :ref:`bluetooth-arch` page.
By default, the Matter bridge application has SMP enabled and supports security levels 2, 3 and 4.

You can disable the Bluetooth LE security mechanisms by setting the :kconfig:option:`CONFIG_BT_SMP` Kconfig option to ``n``.
This is strongly not recommended, as it leads to unencrypted communication with bridged devices, which makes them vulnerable to the security attacks.

You can select the minimum security level required by the application.
When selected, the Matter bridge will require setting the selected minimum level from the connected Bluetooth LE bridged device.
If the bridged device supports also levels higher than the selected minimum, the devices may negotiate using the highest shared security level.
In case the bridged device does not support the minimum required level, the connection will be terminated.
To select the minimum security level, set the :kconfig:option:`CONFIG_BRIDGE_BT_MINIMUM_SECURITY_LEVEL` Kconfig option to ``2``, ``3`` or ``4``.

.. _matter_bridge_app_build_types:

Matter bridge build types
Expand Down Expand Up @@ -458,6 +519,7 @@ After building the sample and programming it to your development kit, complete t
* :ref:`peripheral_esp`

#. Connect the development kit that is running the Bluetooth LE sample to the PC.
#. |connect_terminal_ANSI|
#. Using the terminal emulator connected to the bridge, run the following :ref:`Matter CLI command <matter_bridge_cli>` to scan for available Bluetooth LE devices:

.. code-block:: console
Expand Down Expand Up @@ -496,6 +558,49 @@ After building the sample and programming it to your development kit, complete t
.. parsed-literal::
:class: highlight
I: Connected: C7:44:0F:3E:BB:F0 (random)
---------------------------------------------------------------------
| Bridged Bluetooth LE device authentication |
| |
| Insert pin code displayed by the Bluetooth LE peripheral device |
| to authenticate the pairing operation. |
| |
| To do that, use matter_bridge pincode <pincode> shell command. |
---------------------------------------------------------------------
#. Write down the authentication pincode value from the Bluetooth LE bridged device terminal.
The terminal output is similar to the following one:

.. parsed-literal::
:class: highlight
Passkey for FD:D6:53:EB:92:3A (random): 350501
In the above example output, the displayed pincode value is ``350501``.
It will be used in the next steps as *<bluetooth_authentication_pincode>*.
#. Insert the authentication pincode of the bridged device in the Matter bridge terminal.
To insert the pincode, run the following :ref:`Matter CLI command <matter_bridge_cli>` with *<bluetooth_authentication_pincode>* replaced by the value read in the previous step:

.. parsed-literal::
:class: highlight
uart:~$ matter_bridge pincode *<bluetooth_authentication_pincode>*
For example, if you want to add a new Bluetooth LE bridged device with pincode ``350501``, use the following command:

.. code-block:: console
uart:~$ matter_bridge pincode 350501
The terminal output is similar to the following one:

.. parsed-literal::
:class: highlight
I: Pairing completed: E3:9D:5E:51:AD:14 (random), bonded: 1
I: Security changed: level 4
I: The GATT discovery completed
I: Added device to dynamic endpoint 3 (index=0)
I: Added device to dynamic endpoint 4 (index=1)
I: Created 0x100 device type on the endpoint 3
Expand Down
Expand Up @@ -338,7 +338,7 @@ CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(int deviceType, bt_addr_le_t bt
return err;
}

CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel)
CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel, BLEConnectivityManager::ConnectionSecurityRequest * request)
{
BLEBridgedDeviceProvider *provider =
static_cast<BLEBridgedDeviceProvider *>(BleBridgedDeviceFactory::GetDataProviderFactory().Create(
Expand Down Expand Up @@ -375,7 +375,7 @@ CHIP_ERROR BleBridgedDeviceFactory::CreateDevice(uint16_t uuid, bt_addr_le_t btA
contextPtr->address = btAddress;

provider->InitializeBridgedDevice(btAddress, BluetoothDeviceConnected, contextPtr.get());
err = BLEConnectivityManager::Instance().Connect(provider);
err = BLEConnectivityManager::Instance().Connect(provider, request);

if (err == CHIP_NO_ERROR) {
contextPtr.release();
Expand Down
Expand Up @@ -76,10 +76,12 @@ CHIP_ERROR CreateDevice(int deviceType, bt_addr_le_t btAddress, const char *node
* @param uuid the Bluetooth LE service UUID of a bridged device provider that will be paired with bridged device
* @param btAddress the Bluetooth LE address of a device to be bridged with created Matter device
* @param nodeLabel node label of a Matter device to be created
* @param request address of connection request object for handling additional security information requiered by the connection.
* Can be nullptr, if connection does not use security.
* @return CHIP_NO_ERROR on success
* @return other error code on failure
*/
CHIP_ERROR CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel);
CHIP_ERROR CreateDevice(uint16_t uuid, bt_addr_le_t btAddress, const char *nodeLabel, BLEConnectivityManager::ConnectionSecurityRequest * request = nullptr);

/**
* @brief Remove bridged device.
Expand Down
52 changes: 52 additions & 0 deletions applications/matter_bridge/src/bridge_shell.cpp
Expand Up @@ -15,6 +15,26 @@

#include <zephyr/shell/shell.h>

#if defined(CONFIG_BRIDGED_DEVICE_BT) && defined(CONFIG_BT_SMP)
static void BluetoothConnectionSecurityRequest(void *context)
{
if (!context) {
return;
}

const struct shell *shell = reinterpret_cast<struct shell *>(context);

shell_fprintf(shell, SHELL_INFO, "---------------------------------------------------------------------\n");
shell_fprintf(shell, SHELL_INFO, "| Bridged Bluetooth LE device authentication |\n");
shell_fprintf(shell, SHELL_INFO, "| |\n");
shell_fprintf(shell, SHELL_INFO, "| Insert pin code displayed by the Bluetooth LE peripheral device |\n");
shell_fprintf(shell, SHELL_INFO, "| to authenticate the pairing operation. |\n");
shell_fprintf(shell, SHELL_INFO, "| |\n");
shell_fprintf(shell, SHELL_INFO, "| To do that, use matter_bridge pincode <pincode> shell command. |\n");
shell_fprintf(shell, SHELL_INFO, "---------------------------------------------------------------------\n");
}
#endif /* CONFIG_BRIDGED_DEVICE_BT && CONFIG_BT_SMP */

static int AddBridgedDeviceHandler(const struct shell *shell, size_t argc, char **argv)
{
char *nodeLabel = nullptr;
Expand All @@ -39,7 +59,14 @@ static int AddBridgedDeviceHandler(const struct shell *shell, size_t argc, char
shell_fprintf(shell, SHELL_ERROR, "Invalid Bluetooth LE device index.\n");
}

#ifdef CONFIG_BT_SMP
BLEConnectivityManager::ConnectionSecurityRequest request;
request.mCallback = BluetoothConnectionSecurityRequest;
request.mContext = const_cast<struct shell *>(shell);
result = BleBridgedDeviceFactory::CreateDevice(uuid, address, nodeLabel, &request);
#else
result = BleBridgedDeviceFactory::CreateDevice(uuid, address, nodeLabel);
#endif /* CONFIG_BT_SMP */

#elif defined(CONFIG_BRIDGED_DEVICE_SIMULATED)
int deviceType = strtoul(argv[1], NULL, 0);
Expand Down Expand Up @@ -168,6 +195,24 @@ static void BluetoothScanResult(BLEConnectivityManager::ScannedDevice *devices,
}
}

#ifdef CONFIG_BT_SMP
static int InsertBridgedDevicePincodeHandler(const struct shell *shell, size_t argc, char **argv)
{
int bleDeviceIndex = strtoul(argv[0], NULL, 0);
unsigned int pincode = strtoul(argv[1], NULL, 0);

bt_addr_le_t address;
if (BLEConnectivityManager::Instance().GetScannedDeviceAddress(&address, bleDeviceIndex) != CHIP_NO_ERROR) {
shell_fprintf(shell, SHELL_ERROR, "Invalid Bluetooth LE device index.\n");
} else {
shell_fprintf(shell, SHELL_ERROR, "Found device address\n");
}

BLEConnectivityManager::Instance().SetPincode(address, pincode);
return 0;
}
#endif /* CONFIG_BT_SMP */

static int ScanBridgedDeviceHandler(const struct shell *shell, size_t argc, char **argv)
{
shell_fprintf(shell, SHELL_INFO, "Scanning for 10 s ...\n");
Expand Down Expand Up @@ -225,6 +270,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
"Scan for Bluetooth LE devices to bridge. \n"
"Usage: scan\n",
ScanBridgedDeviceHandler, 1, 0),
#ifdef CONFIG_BT_SMP
SHELL_CMD_ARG(pincode, NULL,
"Insert pincode for Bluetooth LE device pairing. \n"
"Usage: pincode <pincode>\n"
"* pincode - is a pin required for Bluetooth LE pairing authentication\n",
InsertBridgedDevicePincodeHandler, 2, 0),
#endif /* CONFIG_BT_SMP */
#endif /* CONFIG_BRIDGED_DEVICE_BT */
SHELL_SUBCMD_SET_END);

Expand Down
5 changes: 3 additions & 2 deletions applications/matter_bridge/sysbuild/hci_ipc/prj.conf
Expand Up @@ -17,11 +17,12 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
## BT configuration
CONFIG_BT=y
CONFIG_BT_HCI_RAW=y
CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_CONN=10
CONFIG_BT_CTLR_ASSERT_HANDLER=y
CONFIG_BT_HCI_RAW_RESERVE=1
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=n
CONFIG_BT_CENTRAL=y
CONFIG_BT_EXT_ADV=y
CONFIG_BT_BUF_ACL_RX_SIZE=502
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
Expand Down
Expand Up @@ -259,6 +259,7 @@ Matter Bridge
* Support for On/Off Light Switch bridged device type.
* Support for bindings to the On/Off Light Switch device implementation.
* Guide about extending the application by adding support for a new Matter device type, a new Bluetooth LE service or a new protocol.
* Support for Bluetooth LE Security Manager Protocol that allows to establish secure session with bridged Bluetooth LE devices.

Samples
=======
Expand Down
10 changes: 10 additions & 0 deletions samples/matter/common/src/bridge/Kconfig
Expand Up @@ -30,4 +30,14 @@ config BRIDGE_BT_RECOVERY_SCAN_TIMEOUT_MS
int "Time (in ms) within which the Bridge will try to re-establish a connection to the lost BT LE device"
default 2000

config BRIDGE_BT_MINIMUM_SECURITY_LEVEL
int "Minimum Bluetooth security level of bridged devices that will be accepted by the bridge device"
default 2
range 2 4
depends on BT_SMP
help
The minimum Bluetooth security level means that the bridged devices using this or a higher level will be
allowed to connect to the bridge. The level cannot be set to a value smaller than 2, as it would mean that
the communication with the connected devices will not be encrypted, what is not considered to be secure.

endif
6 changes: 5 additions & 1 deletion samples/matter/common/src/bridge/ble_bridged_device.h
Expand Up @@ -28,7 +28,10 @@ struct BLEBridgedDevice {

class BLEBridgedDeviceProvider : public BridgedDeviceDataProvider {
public:
explicit BLEBridgedDeviceProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback) : BridgedDeviceDataProvider(updateCallback, commandCallback) {}
BLEBridgedDeviceProvider(UpdateAttributeCallback updateCallback, InvokeCommandCallback commandCallback)
: BridgedDeviceDataProvider(updateCallback, commandCallback)
{
}
~BLEBridgedDeviceProvider() { BLEConnectivityManager::Instance().RemoveBLEProvider(GetBtAddress()); }

virtual bt_uuid *GetServiceUuid() = 0;
Expand All @@ -45,6 +48,7 @@ class BLEBridgedDeviceProvider : public BridgedDeviceDataProvider {

BLEBridgedDevice &GetBLEBridgedDevice() { return mDevice; }
void SetConnectionObject(bt_conn *conn) { mDevice.mConn = conn; }
bt_conn *GetConnectionObject() { return mDevice.mConn; }
void RemoveConnectionObject() { mDevice.mConn = nullptr; }

/**
Expand Down

0 comments on commit f84125d

Please sign in to comment.