Skip to content

Commit 688f8ac

Browse files
committed
Feat: Implement clearAllBondings using iterative gap_delete_bonding
This commit introduces a functional implementation for `BLESecureClass::clearAllBondings()`, designed to remove all LE bonding information stored by BTstack. The method now performs the following: 1. **Initial State Logging**: Dumps the LE Device Database using `le_device_db_dump()` and logs the count of bonded devices reported by `le_device_db_count()` before any deletion attempts. 2. **Iterative Deletion**: * Loops through all potential physical slots in the LE Device Database (up to `NVM_NUM_DEVICE_DB_ENTRIES`). * For each slot, it calls `le_device_db_info()` to retrieve the address and address type of any stored bond. * If a valid LE device (public or random address type) is found in a slot, `gap_delete_bonding(addr_type, addr)` is invoked for that specific device. This is the recommended high-level API to request bond removal. * `le_device_db_dump()` is called after each `gap_delete_bonding` call to provide insight into the immediate effect on the database (though flash changes might have backend latencies). 3. **Final State Logging**: After iterating through all slots, `le_device_db_dump()` is called again, and the final count from `le_device_db_count()` is logged to assess the outcome. 4. **Informational Messages**: Includes detailed serial logging throughout the process to aid in debugging and understanding the function's behavior. This approach aims to systematically request the deletion of each stored bond via the GAP layer, which should then instruct the LE Device DB (TLV on flash) and the Security Manager to remove the associated security information. Also added a test example `ClearBondingTest`` for the new function.
1 parent 1a280cb commit 688f8ac

File tree

10 files changed

+368
-6
lines changed

10 files changed

+368
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ The library includes several example platformIO projects demonstrating its usage
316316
- **SecurePairingMedium**: Basic encryption without MITM protection using the "Just Works" method
317317
- **SecurePairingHigh**: Encryption with MITM protection using passkey or numeric comparison
318318
- **SecurePairingHighSC**: The highest security level using Secure Connections
319+
- **ClearBondingTest**: Clears bonding information in flash memory via BOOTSEL button press
319320
320321
### Test with nRF Connect mobile app
321322
- connect pico-W to computer with USB
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.pio
2+
.vscode/.browse.c_cpp.db*
3+
.vscode/c_cpp_properties.json
4+
.vscode/launch.json
5+
.vscode/ipch
6+
logs/
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
// See http://go.microsoft.com/fwlink/?LinkId=827846
3+
// for the documentation about the extensions.json format
4+
"recommendations": [
5+
"platformio.platformio-ide"
6+
],
7+
"unwantedRecommendations": [
8+
"ms-vscode.cpptools-extension-pack"
9+
]
10+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
This directory is intended for project header files.
3+
4+
A header file is a file containing C declarations and macro definitions
5+
to be shared between several project source files. You request the use of a
6+
header file in your project source file (C, C++, etc) located in `src` folder
7+
by including it, with the C preprocessing directive `#include'.
8+
9+
```src/main.c
10+
11+
#include "header.h"
12+
13+
int main (void)
14+
{
15+
...
16+
}
17+
```
18+
19+
Including a header file produces the same results as copying the header file
20+
into each source file that needs it. Such copying would be time-consuming
21+
and error-prone. With a header file, the related declarations appear
22+
in only one place. If they need to be changed, they can be changed in one
23+
place, and programs that include the header file will automatically use the
24+
new version when next recompiled. The header file eliminates the labor of
25+
finding and changing all the copies as well as the risk that a failure to
26+
find one copy will result in inconsistencies within a program.
27+
28+
In C, the convention is to give header files names that end with `.h'.
29+
30+
Read more about using header files in official GCC documentation:
31+
32+
* Include Syntax
33+
* Include Operation
34+
* Once-Only Headers
35+
* Computed Includes
36+
37+
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
This directory is intended for project specific (private) libraries.
3+
PlatformIO will compile them to static libraries and link into the executable file.
4+
5+
The source code of each library should be placed in a separate directory
6+
("lib/your_library_name/[Code]").
7+
8+
For example, see the structure of the following example libraries `Foo` and `Bar`:
9+
10+
|--lib
11+
| |
12+
| |--Bar
13+
| | |--docs
14+
| | |--examples
15+
| | |--src
16+
| | |- Bar.c
17+
| | |- Bar.h
18+
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
19+
| |
20+
| |--Foo
21+
| | |- Foo.c
22+
| | |- Foo.h
23+
| |
24+
| |- README --> THIS FILE
25+
|
26+
|- platformio.ini
27+
|--src
28+
|- main.c
29+
30+
Example contents of `src/main.c` using Foo and Bar:
31+
```
32+
#include <Foo.h>
33+
#include <Bar.h>
34+
35+
int main (void)
36+
{
37+
...
38+
}
39+
40+
```
41+
42+
The PlatformIO Library Dependency Finder will find automatically dependent
43+
libraries by scanning project source files.
44+
45+
More information about PlatformIO Library Dependency Finder
46+
- https://docs.platformio.org/page/librarymanager/ldf.html
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; PlatformIO Project Configuration File
2+
;
3+
; Build options: build flags, source filter
4+
; Upload options: custom upload port, speed and extra flags
5+
; Library options: dependencies, extra library storages
6+
; Advanced options: extra scripting
7+
;
8+
; Please visit documentation for the other options and examples
9+
; https://docs.platformio.org/page/projectconf.html
10+
11+
[env:rpipicow]
12+
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
13+
board = rpipicow
14+
framework = arduino
15+
monitor_filters = default, time, log2file
16+
board_build.core = earlephilhower
17+
board_build.filesystem_size = 0.5m
18+
build_flags =
19+
-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH
20+
-DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV4
21+
; lib_extra_dirs = ../../..
22+
lib_deps =
23+
; https://github.com/IoT-gamer/pico-ble-secure
24+
pico-ble-secure
25+
pico-ble-notify
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include <Arduino.h>
2+
#include <BTstackLib.h>
3+
#include <BLESecure.h>
4+
#include "ble/le_device_db.h" // required for le_device_db_dump
5+
6+
// Configuration
7+
const char* DEVICE_NAME = "BondClearTestPico";
8+
const BLESecurityLevel SECURITY_LEVEL = SECURITY_MEDIUM;
9+
const io_capability_t IO_CAPABILITY = IO_CAPABILITY_NO_INPUT_NO_OUTPUT;
10+
11+
// Global State
12+
bool deviceConnected = false;
13+
BLEDevice* connectedDevicePtr = nullptr;
14+
15+
// Callbacks
16+
void bleDeviceConnectedCallback(BLEStatus status, BLEDevice* device) {
17+
if (status == BLE_STATUS_OK) {
18+
Serial.println("Device connected!");
19+
digitalWrite(LED_BUILTIN, HIGH);
20+
deviceConnected = true;
21+
connectedDevicePtr = device;
22+
} else {
23+
Serial.print("Connection failed, status: ");
24+
Serial.println(status);
25+
digitalWrite(LED_BUILTIN, LOW);
26+
}
27+
}
28+
29+
void bleDeviceDisconnectedCallback(BLEDevice* device) {
30+
Serial.println("Device disconnected!");
31+
digitalWrite(LED_BUILTIN, LOW);
32+
deviceConnected = false;
33+
connectedDevicePtr = nullptr;
34+
// Only restart advertising if we are not in the middle of a BOOTSEL reset
35+
// The BOOTSEL logic will handle restarting advertising.
36+
if (!BOOTSEL) { // Assuming BOOTSEL is low when not pressed after initial check
37+
Serial.println("Restarting advertising after normal disconnect.");
38+
BTstack.startAdvertising();
39+
}
40+
}
41+
42+
void onPairingStatusCallback(BLEPairingStatus status, BLEDevice* device) {
43+
Serial.print("Pairing Status: ");
44+
switch (status) {
45+
case PAIRING_IDLE: Serial.println("IDLE"); break;
46+
case PAIRING_STARTED: Serial.println("STARTED"); break;
47+
case PAIRING_COMPLETE:
48+
Serial.println("COMPLETE - Device Bonded/Re-encrypted.");
49+
Serial.println("LE Device DB Dump after pairing/re-encryption:");
50+
le_device_db_dump(); // See what's in the DB now
51+
break;
52+
case PAIRING_FAILED: Serial.println("FAILED"); break;
53+
default: Serial.println("UNKNOWN"); break;
54+
}
55+
}
56+
57+
void setup() {
58+
Serial.begin(115200);
59+
// Wait for serial, with timeout, but not indefinitely
60+
// unsigned long setupStartTime = millis();
61+
// while (!Serial && (millis() - setupStartTime < 3000)) {
62+
// delay(100);
63+
// }
64+
while (!Serial) delay(10); // Wait for serial to be ready
65+
delay(100); // Give some time for the serial to stabilize
66+
Serial.println();
67+
Serial.println("BLESecure ClearBondingTest Example (with LTK Reconstruction Toggle)");
68+
69+
pinMode(LED_BUILTIN, OUTPUT);
70+
digitalWrite(LED_BUILTIN, LOW);
71+
72+
BTstack.setup(DEVICE_NAME); // Initializes BTstack, HCI, L2CAP, SM, GATT client/server
73+
74+
// Initial BLESecure configuration for normal operation
75+
BLESecure.begin(IO_CAPABILITY);
76+
BLESecure.setSecurityLevel(SECURITY_LEVEL, true); // Enable bonding
77+
BLESecure.requestPairingOnConnect(true);
78+
BLESecure.allowReconnectionWithoutDatabaseEntry(true); // Default: allow LTK reconstruction
79+
80+
BLESecure.setBLEDeviceConnectedCallback(bleDeviceConnectedCallback);
81+
BLESecure.setBLEDeviceDisconnectedCallback(bleDeviceDisconnectedCallback);
82+
BLESecure.setPairingStatusCallback(onPairingStatusCallback);
83+
84+
BTstack.startAdvertising();
85+
Serial.println("Advertising started. Waiting for connections...");
86+
Serial.println("Press and HOLD BOOTSEL button to clear all bondings and disable LTK reconstruction for next pairing.");
87+
}
88+
89+
void loop() {
90+
BTstack.loop();
91+
92+
static bool bootsel_action_taken = false;
93+
static unsigned long bootsel_press_start_time = 0;
94+
const unsigned long BOOTSEL_HOLD_DURATION_MS = 500;
95+
96+
if (BOOTSEL) {
97+
if (bootsel_press_start_time == 0) {
98+
bootsel_press_start_time = millis();
99+
} else if (!bootsel_action_taken && (millis() - bootsel_press_start_time >= BOOTSEL_HOLD_DURATION_MS)) {
100+
Serial.println("BOOTSEL button held - triggering bond clear action!");
101+
102+
if (deviceConnected && connectedDevicePtr) {
103+
Serial.println("Disconnecting current device...");
104+
BTstack.bleDisconnect(connectedDevicePtr);
105+
// Give BTstack time to process disconnection
106+
for(int i=0; i<100; ++i) { BTstack.loop(); delay(10); }
107+
}
108+
109+
Serial.println("Attempting to clear all BLE bondings (e.g., flash erase)...");
110+
BLESecure.clearAllBondings(); // This is your v6 from Canvas (attempts flash erase)
111+
112+
Serial.println("BOOTSEL: Temporarily DISALLOWING LTK reconstruction for next pairing attempt.");
113+
BLESecure.allowReconnectionWithoutDatabaseEntry(false); // *** KEY STEP ***
114+
115+
// Re-initialize BLESecure's SM settings after clearing and changing LTK policy
116+
Serial.println("BOOTSEL: Re-applying Security Manager settings.");
117+
BLESecure.begin(IO_CAPABILITY);
118+
BLESecure.setSecurityLevel(SECURITY_LEVEL, true);
119+
BLESecure.requestPairingOnConnect(true);
120+
// At this point, LTK reconstruction is still false.
121+
// It will be set back to true only after a successful new pairing,
122+
// or upon next full device reset/setup.
123+
124+
Serial.println("BOOTSEL: Restarting advertising...");
125+
BTstack.startAdvertising();
126+
127+
bootsel_action_taken = true;
128+
Serial.println("Action complete. Release BOOTSEL. Pico is ready for a fresh pairing.");
129+
}
130+
} else {
131+
if (bootsel_press_start_time != 0) { // If it was pressed
132+
Serial.println("BOOTSEL button released.");
133+
}
134+
bootsel_press_start_time = 0;
135+
bootsel_action_taken = false;
136+
}
137+
138+
static unsigned long lastBlinkTime = 0;
139+
if (!deviceConnected && (millis() - lastBlinkTime > 1000)) {
140+
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
141+
lastBlinkTime = millis();
142+
}
143+
if(deviceConnected) {
144+
digitalWrite(LED_BUILTIN, HIGH);
145+
}
146+
147+
delay(10);
148+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
This directory is intended for PlatformIO Test Runner and project tests.
3+
4+
Unit Testing is a software testing method by which individual units of
5+
source code, sets of one or more MCU program modules together with associated
6+
control data, usage procedures, and operating procedures, are tested to
7+
determine whether they are fit for use. Unit testing finds problems early
8+
in the development cycle.
9+
10+
More information about PlatformIO Unit Testing:
11+
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

library.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@
4242
"files": [
4343
"src/main.cpp"
4444
]
45+
},
46+
{
47+
"name": "ClearBondingTest",
48+
"base": "examples/ClearBondingTest",
49+
"files": [
50+
"src/main.cpp"
51+
]
4552
}
4653
],
4754
"export": {
@@ -60,10 +67,16 @@
6067
"examples/SecurePairingHighSC/logs/",
6168
"examples/SecurePairingMedium/.pio",
6269
"examples/SecurePairingMedium/.vscode/.browse.c_cpp.db*",
63-
"examples/SecurePairingMedium.vscode/c_cpp_properties.json",
70+
"examples/SecurePairingMedium/.vscode/c_cpp_properties.json",
6471
"examples/SecurePairingMedium/.vscode/launch.json",
6572
"examples/SecurePairingMedium/.vscode/ipch",
6673
"examples/SecurePairingMedium/logs/",
74+
"examples/ClearBondingTest/.pio",
75+
"examples/ClearBondingTest/.vscode/.browse.c_cpp.db*",
76+
"examples/ClearBondingTest/.vscode/c_cpp_properties.json",
77+
"examples/ClearBondingTest/.vscode/launch.json",
78+
"examples/ClearBondingTest/.vscode/ipch",
79+
"examples/ClearBondingTest/logs/",
6780
".git",
6881
".github",
6982
"*.sh",

0 commit comments

Comments
 (0)