Skip to content

Commit 3c2c5be

Browse files
authored
Merge pull request #14824 from paul-szczepanek-arm/persistence-fix
BLE: Manual BLE security manager db synchronisation
2 parents dfd8996 + 470917f commit 3c2c5be

File tree

11 files changed

+85
-4
lines changed

11 files changed

+85
-4
lines changed

UNITTESTS/fakes/ble/SecurityManagerImpl_mock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class SecurityManagerMock : public ble::impl::SecurityManager {
3434
MOCK_METHOD(ble_error_t, init, (bool enableBonding, bool requireMITM, SecurityIOCapabilities_t iocaps, const Passkey_t passkey, bool signing, const char *dbFilepath), (override));
3535
MOCK_METHOD(ble_error_t, setDatabaseFilepath, (const char *dbFilepath), (override));
3636
MOCK_METHOD(ble_error_t, preserveBondingStateOnReset, (bool enable), (override));
37+
MOCK_METHOD(ble_error_t, writeBondingStateToPersistentStorage, (), (override));
3738
MOCK_METHOD(ble_error_t, purgeAllBondingState, (), (override));
3839
MOCK_METHOD(ble_error_t, generateWhitelistFromBondTable, (::ble::whitelist_t *whitelist), (const, override));
3940
MOCK_METHOD(ble_error_t, requestPairing, (ble::connection_handle_t connectionHandle), (override));

UNITTESTS/fakes/ble/source/generic/SecurityManagerImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class SecurityManager {
5252

5353
virtual ble_error_t preserveBondingStateOnReset(bool enable) { return BLE_ERROR_NONE; };
5454

55+
virtual ble_error_t writeBondingStateToPersistentStorage() { return BLE_ERROR_NONE; };
56+
5557
////////////////////////////////////////////////////////////////////////////
5658
// List management
5759
//

connectivity/FEATURE_BLE/include/ble/SecurityManager.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,11 +543,28 @@ class SecurityManager
543543
* Normally all bonding information is lost when device is reset, this requests that the stack
544544
* attempts to save the information and reload it during initialisation. This is not guaranteed.
545545
*
546+
* @note This option is itself saved together with bonding data. When data is read after reset,
547+
* the state of this option decides if data should be restored. If this option has not been saved
548+
* the data will not be restored even if partial data is present.
549+
*
546550
* @param[in] enable if true the stack will attempt to preserve bonding information on reset.
547551
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
548552
*/
549553
ble_error_t preserveBondingStateOnReset(bool enable);
550554

555+
/**
556+
* Some or all of bonding information may be stored in memory while in use. This will write
557+
* bonding data to persistent storage. This will have no effect if no persistent storage is enabled.
558+
*
559+
* @note This implicitly also calls preserveBondingStateOnReset(true) inside.
560+
*
561+
* @note Depending on the driver used to implement the storage solution used this may be a disruptive
562+
* operation and may cause active connections to drop due to failed processing deadlines.
563+
*
564+
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
565+
*/
566+
ble_error_t writeBondingStateToPersistentStorage();
567+
551568
////////////////////////////////////////////////////////////////////////////
552569
// List management
553570
//

connectivity/FEATURE_BLE/source/SecurityManager.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ ble_error_t SecurityManager::preserveBondingStateOnReset(bool enable)
4747
return impl->preserveBondingStateOnReset(enable);
4848
}
4949

50+
ble_error_t SecurityManager::writeBondingStateToPersistentStorage()
51+
{
52+
ble_error_t err = impl->preserveBondingStateOnReset(true);
53+
if (err) {
54+
return err;
55+
}
56+
return impl->writeBondingStateToPersistentStorage();
57+
}
58+
5059
ble_error_t SecurityManager::purgeAllBondingState()
5160
{
5261
return impl->purgeAllBondingState();

connectivity/FEATURE_BLE/source/generic/FileSecurityDb.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,22 @@ void FileSecurityDb::restore()
361361

362362
void FileSecurityDb::sync(entry_handle_t db_handle)
363363
{
364+
/* if no entry is selected we will sync all entries */
365+
if (db_handle == invalid_entry_handle) {
366+
/* only write the connected devices as others are already written */
367+
for (size_t i = 0; i < get_entry_count(); i++) {
368+
entry_handle_t db_handle = get_entry_handle_by_index(i);
369+
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
370+
371+
if (flags && flags->connected) {
372+
sync(db_handle);
373+
}
374+
}
375+
/* global sync triggers a flush */
376+
fflush(_db_file);
377+
return;
378+
}
379+
364380
entry_t *entry = as_entry(db_handle);
365381
if (!entry) {
366382
return;

connectivity/FEATURE_BLE/source/generic/FileSecurityDb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class FileSecurityDb : public SecurityDb {
136136

137137
virtual void restore();
138138

139-
virtual void sync(entry_handle_t db_handle);
139+
virtual void sync(entry_handle_t db_handle = invalid_entry_handle);
140140

141141
virtual void set_restore(bool reload);
142142

connectivity/FEATURE_BLE/source/generic/KVStoreSecurityDb.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,22 @@ void KVStoreSecurityDb::restore()
333333

334334
void KVStoreSecurityDb::sync(entry_handle_t db_handle)
335335
{
336+
/* storage synchronisation is handled by KVStore itself, no explicit flushing */
337+
338+
/* if no entry is selected we will sync all entries */
339+
if (db_handle == invalid_entry_handle) {
340+
/* only write the connected devices as others are already written */
341+
for (size_t i = 0; i < get_entry_count(); i++) {
342+
entry_handle_t db_handle = get_entry_handle_by_index(i);
343+
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
344+
345+
if (flags && flags->connected) {
346+
sync(db_handle);
347+
}
348+
}
349+
return;
350+
}
351+
336352
entry_t *entry = as_entry(db_handle);
337353
if (!entry) {
338354
return;

connectivity/FEATURE_BLE/source/generic/KVStoreSecurityDb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class KVStoreSecurityDb : public SecurityDb {
200200

201201
virtual void restore();
202202

203-
virtual void sync(entry_handle_t db_handle);
203+
virtual void sync(entry_handle_t db_handle = invalid_entry_handle);
204204

205205
virtual void set_restore(bool reload);
206206

connectivity/FEATURE_BLE/source/generic/SecurityDb.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class SecurityDb {
113113
*/
114114
typedef void* entry_handle_t;
115115

116+
static constexpr entry_handle_t invalid_entry_handle = nullptr;
117+
116118
/* callbacks for asynchronous data retrieval from the security db */
117119

118120
typedef mbed::Callback<void(entry_handle_t, const SecurityEntryKeys_t*)>
@@ -520,9 +522,13 @@ class SecurityDb {
520522
virtual void restore();
521523

522524
/**
523-
* Flush all values which might be stored in memory into NVM.
525+
* Write all values and attempt to sync persistent storage. Passing in an optional valid
526+
* db_handle will only write the given entry and not attempt to flush buffers.
527+
*
528+
* @param db_handle database entry to write. If invalid all entries are written and
529+
* persistent storage attempts to sync (flush buffers).
524530
*/
525-
virtual void sync(entry_handle_t db_handle);
531+
virtual void sync(entry_handle_t db_handle = invalid_entry_handle);
526532

527533
/**
528534
* Toggle whether values should be preserved across resets.

connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,18 @@ ble_error_t SecurityManager::preserveBondingStateOnReset(bool enabled)
222222
return BLE_ERROR_NONE;
223223
}
224224

225+
226+
ble_error_t SecurityManager::writeBondingStateToPersistentStorage()
227+
{
228+
tr_info("Writing bonding to storage");
229+
if (!_db) {
230+
tr_error("Failure, DB not initialized");
231+
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
232+
}
233+
_db->sync();
234+
return BLE_ERROR_NONE;
235+
}
236+
225237
////////////////////////////////////////////////////////////////////////////
226238
// List management
227239
//

0 commit comments

Comments
 (0)