Skip to content

Commit f2ae756

Browse files
committed
Add option for Bluetooth security
Under settings - Bluetooth add BT Security with settings: * Secured - enable Bluetooth security (watch is rebooted on change); * Pairable - temporary make watch discoverable and accept new pairings. The Secured setting: * requests encryption and authentication for BLE characteristics; * allows only encrypted, authenticated (by PIN) and bonded pairing; * allows new pairing only when Pairable setting is enabled; * enables Bluetooth MAC address randomization (BLE RPA with random IRK); * removes all data fields from advertisements after pairing; * uses cryptographically strong RNG for pairing/bonding PIN; * explicitly verifies connection security for sensitive-services; * ensures the watch is bonded with no more than 1 single device; * watch gets rebooted when the Secured setting is changed. The Pairable setting: * temporary sends full advertisements and allows new pairing/bonding; * gets automatically disabled when leaving BT Security screen. This PR maintains compatibility with insecure companion apps. When the Secured setting is disabled the only behavior change is verification by the sensitive-services that Bluetooth is Enabled. The sensitive-services are: * DfuService (allows to compromise watch) * FSService (allows to compromise watch) * HeartRateService (provides data about watch user) * MotionService (provides data about watch user)
1 parent 8250565 commit f2ae756

27 files changed

Lines changed: 571 additions & 111 deletions

src/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ list(APPEND SOURCE_FILES
420420
displayapp/screens/settings/SettingChimes.cpp
421421
displayapp/screens/settings/SettingShakeThreshold.cpp
422422
displayapp/screens/settings/SettingBluetooth.cpp
423+
displayapp/screens/settings/SettingBluetoothMain.cpp
424+
displayapp/screens/settings/SettingBluetoothSecurity.cpp
423425
displayapp/screens/settings/SettingOTA.cpp
424426

425427
## Watch faces
@@ -795,6 +797,7 @@ add_definitions(-DFREERTOS)
795797
add_definitions(-D__STACK_SIZE=1024)
796798
add_definitions(-D__HEAP_SIZE=0)
797799
add_definitions(-DMYNEWT_VAL_BLE_LL_RFMGMT_ENABLE_TIME=1500)
800+
add_definitions(-DMYNEWT_VAL_BLE_RPA_TIMEOUT=900)
798801
add_definitions(-DLFS_CONFIG=libs/lfs_config.h)
799802

800803
# _sbrk is purposefully not implemented so that builds fail when it is used

src/components/ble/AlertNotificationService.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <hal/nrf_rtc.h>
33
#include <cstring>
44
#include <algorithm>
5+
#include "components/ble/NimbleController.h"
56
#include "components/ble/NotificationManager.h"
67
#include "systemtask/SystemTask.h"
78

@@ -17,6 +18,8 @@ int AlertNotificationCallback(uint16_t /*conn_handle*/, uint16_t /*attr_handle*/
1718
}
1819

1920
void AlertNotificationService::Init() {
21+
systemTask.nimble().AddCharacteristicSecurity(serviceDefinition);
22+
2023
int res;
2124
res = ble_gatts_count_cfg(serviceDefinition);
2225
ASSERT(res == 0);

src/components/ble/BatteryInformationService.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "components/ble/BatteryInformationService.h"
22
#include <nrf_log.h>
33
#include "components/battery/BatteryController.h"
4+
#include "components/ble/NimbleController.h"
45

56
using namespace Pinetime::Controllers;
67

@@ -12,8 +13,9 @@ int BatteryInformationServiceCallback(uint16_t /*conn_handle*/, uint16_t attr_ha
1213
return batteryInformationService->OnBatteryServiceRequested(attr_handle, ctxt);
1314
}
1415

15-
BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController)
16+
BatteryInformationService::BatteryInformationService(Controllers::NimbleController& nimble, Controllers::Battery& batteryController)
1617
: batteryController {batteryController},
18+
nimble {nimble},
1719
characteristicDefinition {{.uuid = &batteryLevelUuid.u,
1820
.access_cb = BatteryInformationServiceCallback,
1921
.arg = this,
@@ -30,6 +32,8 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte
3032
}
3133

3234
void BatteryInformationService::Init() {
35+
nimble.AddCharacteristicSecurity(serviceDefinition);
36+
3337
int res = 0;
3438
res = ble_gatts_count_cfg(serviceDefinition);
3539
ASSERT(res == 0);

src/components/ble/BatteryInformationService.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ namespace Pinetime {
1212

1313
namespace Controllers {
1414
class Battery;
15+
class NimbleController;
1516

1617
class BatteryInformationService {
1718
public:
18-
BatteryInformationService(Controllers::Battery& batteryController);
19+
BatteryInformationService(Controllers::NimbleController& nimble, Controllers::Battery& batteryController);
1920
void Init();
2021

2122
int OnBatteryServiceRequested(uint16_t attributeHandle, ble_gatt_access_ctxt* context);
2223
void NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level);
2324

2425
private:
2526
Controllers::Battery& batteryController;
27+
Controllers::NimbleController& nimble;
2628
static constexpr uint16_t batteryInformationServiceId {0x180F};
2729
static constexpr uint16_t batteryLevelId {0x2A19};
2830

src/components/ble/CurrentTimeService.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "components/ble/CurrentTimeService.h"
2+
#include "components/ble/NimbleController.h"
23
#include <nrf_log.h>
34

45
using namespace Pinetime::Controllers;
@@ -24,6 +25,8 @@ int CurrentTimeService::OnCurrentTimeServiceAccessed(struct ble_gatt_access_ctxt
2425
}
2526

2627
void CurrentTimeService::Init() {
28+
nimble.AddCharacteristicSecurity(serviceDefinition);
29+
2730
int res;
2831
res = ble_gatts_count_cfg(serviceDefinition);
2932
ASSERT(res == 0);
@@ -97,7 +100,7 @@ int CurrentTimeService::OnLocalTimeAccessed(struct ble_gatt_access_ctxt* ctxt) {
97100
return 0;
98101
}
99102

100-
CurrentTimeService::CurrentTimeService(DateTime& dateTimeController)
103+
CurrentTimeService::CurrentTimeService(NimbleController& nimble, DateTime& dateTimeController)
101104
: characteristicDefinition {
102105

103106
{.uuid = &ctsLtChrUuid.u,
@@ -118,5 +121,6 @@ CurrentTimeService::CurrentTimeService(DateTime& dateTimeController)
118121
.characteristics = characteristicDefinition},
119122
{0},
120123
},
121-
m_dateTimeController {dateTimeController} {
124+
m_dateTimeController {dateTimeController},
125+
nimble{nimble} {
122126
}

src/components/ble/CurrentTimeService.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
namespace Pinetime {
1313
namespace Controllers {
14+
class NimbleController;
15+
1416
class CurrentTimeService {
1517
public:
16-
CurrentTimeService(DateTime& dateTimeController);
18+
CurrentTimeService(NimbleController& nimble, DateTime& dateTimeController);
1719
void Init();
1820

1921
int OnCurrentTimeServiceAccessed(struct ble_gatt_access_ctxt* ctxt);
@@ -52,6 +54,7 @@ namespace Pinetime {
5254
} CtsLocalTimeData;
5355

5456
DateTime& m_dateTimeController;
57+
NimbleController& nimble;
5558
};
5659
}
5760
}

src/components/ble/DfuService.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ DfuService::DfuService(Pinetime::System::SystemTask& systemTask,
7171
}
7272

7373
void DfuService::Init() {
74+
systemTask.nimble().AddCharacteristicSecurity(serviceDefinition);
75+
7476
int res;
7577
res = ble_gatts_count_cfg(serviceDefinition);
7678
ASSERT(res == 0);
@@ -90,6 +92,8 @@ int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandl
9092
systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification);
9193
return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
9294
}
95+
if (!systemTask.nimble().IsConnSecurityOK())
96+
return BLE_ATT_ERR_INSUFFICIENT_AUTHEN;
9397
#endif
9498

9599
if (bleController.IsFirmwareUpdating()) {

src/components/ble/FSService.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ FSService::FSService(Pinetime::System::SystemTask& systemTask, Pinetime::Control
4242
}
4343

4444
void FSService::Init() {
45+
systemTask.nimble().AddCharacteristicSecurity(serviceDefinition);
46+
4547
int res = 0;
4648
res = ble_gatts_count_cfg(serviceDefinition);
4749
ASSERT(res == 0);
@@ -61,6 +63,8 @@ int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attribut
6163
systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification);
6264
return BLE_ATT_ERR_INSUFFICIENT_AUTHOR;
6365
}
66+
if (!systemTask.nimble().IsConnSecurityOK())
67+
return BLE_ATT_ERR_INSUFFICIENT_AUTHEN;
6468
#endif
6569

6670
if (attributeHandle == versionCharacteristicHandle) {

src/components/ble/HeartRateService.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ HeartRateService::HeartRateService(NimbleController& nimble, Controllers::HeartR
3737
}
3838

3939
void HeartRateService::Init() {
40+
nimble.AddCharacteristicSecurity(serviceDefinition);
41+
4042
int res = 0;
4143
res = ble_gatts_count_cfg(serviceDefinition);
4244
ASSERT(res == 0);
@@ -46,6 +48,9 @@ void HeartRateService::Init() {
4648
}
4749

4850
int HeartRateService::OnHeartRateRequested(uint16_t attributeHandle, ble_gatt_access_ctxt* context) {
51+
if (!nimble.IsConnSecurityOK())
52+
return BLE_ATT_ERR_INSUFFICIENT_AUTHEN;
53+
4954
if (attributeHandle == heartRateMeasurementHandle) {
5055
NRF_LOG_INFO("HEARTRATE : handle = %d", heartRateMeasurementHandle);
5156
uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value
@@ -65,7 +70,7 @@ void HeartRateService::OnNewHeartRateValue(uint8_t heartRateValue) {
6570

6671
uint16_t connectionHandle = nimble.connHandle();
6772

68-
if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) {
73+
if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE || !nimble.IsConnSecurityOK()) {
6974
return;
7075
}
7176

src/components/ble/ImmediateAlertService.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask& syste
4848
}
4949

5050
void ImmediateAlertService::Init() {
51+
systemTask.nimble().AddCharacteristicSecurity(serviceDefinition);
52+
5153
int res = 0;
5254
res = ble_gatts_count_cfg(serviceDefinition);
5355
ASSERT(res == 0);

0 commit comments

Comments
 (0)