From 473482d2043e1d8d43af3aa3e04e2bf09cd019bb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 10 May 2018 11:08:31 +0100 Subject: [PATCH 01/18] move securitydb into generic --- features/FEATURE_BLE/ble/SecurityManager.h | 7 +- .../ble/generic/GenericSecurityManager.h | 32 +++--- .../ble/{pal => generic}/MemorySecurityDb.h | 2 +- .../ble/{pal => generic}/SecurityDb.h | 2 +- .../source/generic/GenericSecurityManager.cpp | 99 ++++++++++--------- .../targets/TARGET_CORDIO/CordioBLE.h | 1 - .../TARGET_CORDIO/source/CordioBLE.cpp | 2 - .../TARGET_NRF5/source/nRF5xn.cpp | 2 - .../TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h | 1 - 9 files changed, 75 insertions(+), 73 deletions(-) rename features/FEATURE_BLE/ble/{pal => generic}/MemorySecurityDb.h (99%) rename features/FEATURE_BLE/ble/{pal => generic}/SecurityDb.h (99%) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 11294a7461..461858e66f 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -417,6 +417,9 @@ public: * support out-of-band exchanges of security data. * @param[in] passkey To specify a static passkey. * @param[in] signing Generate and distribute signing key during pairing + * @param[in] dbPath Path to the folder used to store keys in the filesystem, + * if NULL keys will be only stored in memory + * * * @return BLE_ERROR_NONE on success. */ @@ -424,12 +427,14 @@ public: bool requireMITM = true, SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, - bool signing = true) { + bool signing = true, + const uint8_t *dbPath = NULL) { /* Avoid compiler warnings about unused variables. */ (void)enableBonding; (void)requireMITM; (void)iocaps; (void)passkey; + (void)dbPath; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ } diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index c242b7cba6..8ee91e7096 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -19,7 +19,7 @@ #include "ble/pal/GapTypes.h" #include "ble/BLETypes.h" -#include "ble/pal/SecurityDb.h" +#include "ble/generic/SecurityDb.h" #include "platform/Callback.h" #include "ble/pal/ConnectionEventMonitor.h" #include "ble/pal/SigningEventMonitor.h" @@ -37,8 +37,6 @@ class GenericSecurityManager : public SecurityManager, public pal::ConnectionEventMonitor::EventHandler, public pal::SigningEventMonitor::EventHandler { public: - typedef ble::pal::SecurityDistributionFlags_t SecurityDistributionFlags_t; - typedef ble::pal::SecurityEntryKeys_t SecurityEntryKeys_t; /* implements SecurityManager */ @@ -51,7 +49,8 @@ public: bool mitm = true, SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, - bool signing = true + bool signing = true, + const uint8_t* db_path = NULL ); virtual ble_error_t reset(); @@ -236,11 +235,9 @@ public: public: GenericSecurityManager( pal::SecurityManager &palImpl, - pal::SecurityDb &dbImpl, pal::ConnectionEventMonitor &connMonitorImpl, pal::SigningEventMonitor &signingMonitorImpl ) : _pal(palImpl), - _db(dbImpl), _connection_monitor(connMonitorImpl), _signing_monitor(signingMonitorImpl), _default_authentication(0), @@ -308,7 +305,7 @@ private: * @param[in] entryKeys security entry containing keys. */ void enable_encryption_cb( - pal::SecurityDb::entry_handle_t entry, + SecurityDb::entry_handle_t entry, const SecurityEntryKeys_t* entryKeys ); @@ -319,7 +316,7 @@ private: * @param[in] entryKeys security entry containing keys. */ void set_ltk_cb( - pal::SecurityDb::entry_handle_t entry, + SecurityDb::entry_handle_t entry, const SecurityEntryKeys_t* entryKeys ); @@ -330,7 +327,7 @@ private: * @param[in] csrk connection signature resolving key. */ void return_csrk_cb( - pal::SecurityDb::entry_handle_t connection, + SecurityDb::entry_handle_t connection, const csrk_t *csrk, sign_count_t sign_counter ); @@ -342,7 +339,7 @@ private: * @param[in] csrk connection signature resolving key. */ void set_peer_csrk_cb( - pal::SecurityDb::entry_handle_t connection, + SecurityDb::entry_handle_t connection, const csrk_t *csrk, sign_count_t sign_counter ); @@ -407,8 +404,8 @@ private: * @param identity The identity associated with the entry; may be NULL. */ void on_security_entry_retrieved( - pal::SecurityDb::entry_handle_t entry, - const pal::SecurityEntryIdentity_t* identity + SecurityDb::entry_handle_t entry, + const SecurityEntryIdentity_t* identity ); /** @@ -421,12 +418,12 @@ private: * @param count Number of identities entries retrieved. */ void on_identity_list_retrieved( - ble::ArrayView& identity_list, + ble::ArrayView& identity_list, size_t count ); private: - struct ControlBlock_t : public pal::SecurityDistributionFlags_t { + struct ControlBlock_t : public SecurityDistributionFlags_t { ControlBlock_t(); pal::KeyDistribution get_initiator_key_distribution() { @@ -443,7 +440,7 @@ private: }; connection_handle_t connection; - pal::SecurityDb::entry_handle_t db_entry; + SecurityDb::entry_handle_t db_entry; address_t local_address; /**< address used for connection, possibly different from identity */ @@ -473,10 +470,11 @@ private: }; pal::SecurityManager &_pal; - pal::SecurityDb &_db; pal::ConnectionEventMonitor &_connection_monitor; pal::SigningEventMonitor &_signing_monitor; + SecurityDb *_db; + /* OOB data */ address_t _oob_local_address; address_t _oob_peer_address; @@ -718,7 +716,7 @@ public: ControlBlock_t* get_control_block(const address_t &peer_address); - ControlBlock_t* get_control_block(pal::SecurityDb::entry_handle_t db_entry); + ControlBlock_t* get_control_block(SecurityDb::entry_handle_t db_entry); void release_control_block(ControlBlock_t* entry); }; diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h similarity index 99% rename from features/FEATURE_BLE/ble/pal/MemorySecurityDb.h rename to features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index 7616597d6e..624906da36 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -20,7 +20,7 @@ #include "SecurityDb.h" namespace ble { -namespace pal { +namespace generic { /** Naive memory implementation for verification. */ class MemorySecurityDb : public SecurityDb { diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h similarity index 99% rename from features/FEATURE_BLE/ble/pal/SecurityDb.h rename to features/FEATURE_BLE/ble/generic/SecurityDb.h index 3df5f5b9a9..41fa81d89b 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -24,7 +24,7 @@ #include namespace ble { -namespace pal { +namespace generic { /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 6f7e42f69a..51878ef678 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -17,6 +17,8 @@ #include "ble/SecurityManager.h" #include "ble/pal/PalSecurityManager.h" #include "ble/generic/GenericSecurityManager.h" +#include "ble/generic/MemorySecurityDb.h" +#include "ble/generic/FileSecurityDb.h" using ble::pal::advertising_peer_address_type_t; using ble::pal::AuthenticationMask; @@ -37,14 +39,17 @@ ble_error_t GenericSecurityManager::init( bool mitm, SecurityIOCapabilities_t iocaps, const Passkey_t passkey, - bool signing + bool signing, + const uint8_t* db_path ) { ble_error_t err = _pal.initialize(); if (err) { return err; } - _db.restore(); + _db = new (std::nothrow) MemorySecurityDb(); + + _db->restore(); _pal.set_io_capability((io_capability_t::type) iocaps); if (passkey) { @@ -75,16 +80,16 @@ ble_error_t GenericSecurityManager::init( _pal.set_event_handler(this); uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity(); - pal::SecurityEntryIdentity_t** identity_list_p = - new (std::nothrow) pal::SecurityEntryIdentity_t*[resolving_list_capacity]; + SecurityEntryIdentity_t** identity_list_p = + new (std::nothrow) SecurityEntryIdentity_t*[resolving_list_capacity]; if (identity_list_p) { - ArrayView identity_list( + ArrayView identity_list( identity_list_p, resolving_list_capacity ); - _db.get_identity_list( + _db->get_identity_list( mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), identity_list ); @@ -94,7 +99,7 @@ ble_error_t GenericSecurityManager::init( } ble_error_t GenericSecurityManager::reset(void) { - _db.sync(); + _db->sync(); _pal.reset(); SecurityManager::reset(); @@ -102,7 +107,7 @@ ble_error_t GenericSecurityManager::reset(void) { } ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { - _db.set_restore(enabled); + _db->set_restore(enabled); return BLE_ERROR_NONE; } @@ -111,13 +116,13 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { // ble_error_t GenericSecurityManager::purgeAllBondingState(void) { - _db.clear_entries(); + _db->clear_entries(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const { if (eventHandler) { - _db.generate_whitelist_from_bond_table( + _db->generate_whitelist_from_bond_table( mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable), whitelist ); @@ -333,7 +338,7 @@ ble_error_t GenericSecurityManager::enableSigning( cb->signing_requested = true; if (cb->csrk_stored) { /* used the stored ones when available */ - _db.get_entry_peer_csrk( + _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), cb->db_entry ); @@ -471,7 +476,7 @@ ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection if (cb->csrk_stored && (cb->csrk_mitm_protected || !authenticated)) { /* we have a key that is either authenticated or we don't care if it is * so retrieve it from the db now */ - _db.get_entry_peer_csrk( + _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::return_csrk_cb), cb->db_entry ); @@ -658,8 +663,8 @@ ble_error_t GenericSecurityManager::oobReceived( // ble_error_t GenericSecurityManager::init_signing() { - const csrk_t *pcsrk = _db.get_local_csrk(); - sign_count_t local_sign_counter = _db.get_local_sign_counter(); + const csrk_t *pcsrk = _db->get_local_csrk(); + sign_count_t local_sign_counter = _db->get_local_sign_counter(); if (!pcsrk) { csrk_t csrk; @@ -670,8 +675,8 @@ ble_error_t GenericSecurityManager::init_signing() { } pcsrk = &csrk; - _db.set_local_csrk(csrk); - _db.set_local_sign_counter(local_sign_counter); + _db->set_local_csrk(csrk); + _db->set_local_sign_counter(local_sign_counter); } return _pal.set_csrk(*pcsrk, local_sign_counter); @@ -713,7 +718,7 @@ ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connec } if (cb->is_master) { if (cb->ltk_stored) { - _db.get_entry_peer_keys( + _db->get_entry_peer_keys( mbed::callback(this, &GenericSecurityManager::enable_encryption_cb), cb->db_entry ); @@ -727,7 +732,7 @@ ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connec } void GenericSecurityManager::enable_encryption_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { ControlBlock_t *cb = get_control_block(db_entry); @@ -742,7 +747,7 @@ void GenericSecurityManager::enable_encryption_cb( } void GenericSecurityManager::set_ltk_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { ControlBlock_t *cb = get_control_block(db_entry); @@ -757,7 +762,7 @@ void GenericSecurityManager::set_ltk_cb( } void GenericSecurityManager::set_peer_csrk_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const csrk_t *csrk, sign_count_t sign_counter ) { @@ -775,7 +780,7 @@ void GenericSecurityManager::set_peer_csrk_cb( } void GenericSecurityManager::return_csrk_cb( - pal::SecurityDb::entry_handle_t db_entry, + SecurityDb::entry_handle_t db_entry, const csrk_t *csrk, sign_count_t sign_counter ) { @@ -846,13 +851,13 @@ void GenericSecurityManager::on_connected( cb->is_master = (role == Gap::CENTRAL); // get the associated db handle and the distribution flags if any - cb->db_entry = _db.open_entry(peer_address_type, peer_address); + cb->db_entry = _db->open_entry(peer_address_type, peer_address); - const pal::SecurityDistributionFlags_t* dist_flags = - _db.get_distribution_flags(cb->db_entry); + const SecurityDistributionFlags_t* dist_flags = + _db->get_distribution_flags(cb->db_entry); if (dist_flags) { - *static_cast(cb) = *dist_flags; + *static_cast(cb) = *dist_flags; } const bool signing = cb->signing_override_default ? @@ -860,7 +865,7 @@ void GenericSecurityManager::on_connected( _default_key_distribution.get_signing(); if (signing && cb->csrk_stored) { - _db.get_entry_peer_csrk( + _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), cb->db_entry ); @@ -876,15 +881,15 @@ void GenericSecurityManager::on_disconnected( return; } - _db.close_entry(cb->db_entry); + _db->close_entry(cb->db_entry); release_control_block(cb); - _db.sync(); + _db->sync(); } void GenericSecurityManager::on_security_entry_retrieved( - pal::SecurityDb::entry_handle_t entry, - const pal::SecurityEntryIdentity_t* identity + SecurityDb::entry_handle_t entry, + const SecurityEntryIdentity_t* identity ) { if (!identity) { return; @@ -902,7 +907,7 @@ void GenericSecurityManager::on_security_entry_retrieved( } void GenericSecurityManager::on_identity_list_retrieved( - ble::ArrayView& identity_list, + ble::ArrayView& identity_list, size_t count ) { typedef advertising_peer_address_type_t address_type_t; @@ -992,8 +997,8 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t connection ControlBlock_t *cb = get_control_block(connection); if (cb) { // set the distribution flags in the db - _db.set_distribution_flags(cb->db_entry, *cb); - _db.get_entry_identity( + _db->set_distribution_flags(cb->db_entry, *cb); + _db->get_entry_identity( mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved), cb->db_entry ); @@ -1021,7 +1026,7 @@ void GenericSecurityManager::on_signed_write_received( if (!cb) { return; } - _db.set_entry_peer_sign_counter(cb->db_entry, sign_counter); + _db->set_entry_peer_sign_counter(cb->db_entry, sign_counter); } void GenericSecurityManager::on_signed_write_verification_failure( @@ -1050,7 +1055,7 @@ void GenericSecurityManager::on_signed_write_verification_failure( } void GenericSecurityManager::on_signed_write() { - _db.set_local_sign_counter(_db.get_local_sign_counter() + 1); + _db->set_local_sign_counter(_db->get_local_sign_counter() + 1); } void GenericSecurityManager::on_slave_security_request( @@ -1229,7 +1234,7 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( cb->ltk_mitm_protected = cb->mitm_performed; cb->secure_connections_paired = true; - _db.set_entry_peer_ltk(cb->db_entry, ltk); + _db->set_entry_peer_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_ltk( @@ -1241,7 +1246,7 @@ void GenericSecurityManager::on_keys_distributed_ltk( return; } cb->ltk_mitm_protected = cb->mitm_performed; - _db.set_entry_peer_ltk(cb->db_entry, ltk); + _db->set_entry_peer_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_ediv_rand( @@ -1254,7 +1259,7 @@ void GenericSecurityManager::on_keys_distributed_ediv_rand( return; } - _db.set_entry_peer_ediv_rand(cb->db_entry, ediv, rand); + _db->set_entry_peer_ediv_rand(cb->db_entry, ediv, rand); } void GenericSecurityManager::on_keys_distributed_local_ltk( @@ -1266,7 +1271,7 @@ void GenericSecurityManager::on_keys_distributed_local_ltk( return; } - _db.set_entry_local_ltk(cb->db_entry, ltk); + _db->set_entry_local_ltk(cb->db_entry, ltk); } void GenericSecurityManager::on_keys_distributed_local_ediv_rand( @@ -1279,7 +1284,7 @@ void GenericSecurityManager::on_keys_distributed_local_ediv_rand( return; } - _db.set_entry_local_ediv_rand(cb->db_entry, ediv, rand); + _db->set_entry_local_ediv_rand(cb->db_entry, ediv, rand); } void GenericSecurityManager::on_keys_distributed_irk( @@ -1291,7 +1296,7 @@ void GenericSecurityManager::on_keys_distributed_irk( return; } - _db.set_entry_peer_irk(cb->db_entry, irk); + _db->set_entry_peer_irk(cb->db_entry, irk); } void GenericSecurityManager::on_keys_distributed_bdaddr( @@ -1304,7 +1309,7 @@ void GenericSecurityManager::on_keys_distributed_bdaddr( return; } - _db.set_entry_peer_bdaddr( + _db->set_entry_peer_bdaddr( cb->db_entry, (peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS), peer_identity_address @@ -1322,7 +1327,7 @@ void GenericSecurityManager::on_keys_distributed_csrk( cb->csrk_mitm_protected = cb->mitm_performed; - _db.set_entry_peer_csrk(cb->db_entry, csrk); + _db->set_entry_peer_csrk(cb->db_entry, csrk); eventHandler->signingKey( connection, @@ -1341,7 +1346,7 @@ void GenericSecurityManager::on_ltk_request( return; } - _db.get_entry_local_keys( + _db->get_entry_local_keys( mbed::callback(this, &GenericSecurityManager::set_ltk_cb), cb->db_entry, ediv, @@ -1352,7 +1357,7 @@ void GenericSecurityManager::on_ltk_request( /* control blocks list management */ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : - pal::SecurityDistributionFlags_t(), + SecurityDistributionFlags_t(), connection(0), db_entry(0), local_address(), @@ -1379,7 +1384,7 @@ void GenericSecurityManager::on_ltk_request(connection_handle_t connection) return; } - _db.get_entry_local_keys( + _db->get_entry_local_keys( mbed::callback(this, &GenericSecurityManager::set_ltk_cb), cb->db_entry ); @@ -1428,7 +1433,7 @@ GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_bloc } GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block( - pal::SecurityDb::entry_handle_t db_entry + SecurityDb::entry_handle_t db_entry ) { for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { if (!_control_blocks[i].connected) { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index 2d56c98f3e..e4eeafba1d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -30,7 +30,6 @@ #include "CordioPalGenericAccessService.h" #include "ble/generic/GenericGap.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/MemorySecurityDb.h" #include "ble/pal/SimpleEventQueue.h" namespace ble { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 46ec738a0e..97b754dd5e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -204,11 +204,9 @@ generic::GenericGattClient& BLE::getGattClient() SecurityManager& BLE::getSecurityManager() { - static pal::MemorySecurityDb m_db; static SigningEventMonitorProxy signing_event_monitor(*this); static generic::GenericSecurityManager m_instance( pal::vendor::cordio::CordioSecurityManager::get_security_manager(), - m_db, getGap(), signing_event_monitor ); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.cpp index 0f25e1634b..e3408976a5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.cpp @@ -208,7 +208,6 @@ SecurityManager& nRF5xn::getSecurityManager() const SecurityManager& nRF5xn::getSecurityManager() const { - static ble::pal::MemorySecurityDb m_db; ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal = ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager(); static struct : ble::pal::SigningEventMonitor { @@ -217,7 +216,6 @@ const SecurityManager& nRF5xn::getSecurityManager() const static ble::generic::GenericSecurityManager m_instance( m_pal, - m_db, const_cast(getGap()), dummy_signing_event_monitor ); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h index dfaf59cc26..8829d72347 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h @@ -22,7 +22,6 @@ #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/MemorySecurityDb.h" #include "ble/pal/SimpleEventQueue.h" #include "nRF5xPalSecurityManager.h" From afa4bdcf1a8c96fecd2c0d612823d679ea462cf0 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 11 May 2018 10:19:48 +0100 Subject: [PATCH 02/18] pull common logic into secure db --- .../ble/generic/MemorySecurityDb.h | 120 +++++++----------- features/FEATURE_BLE/ble/generic/SecurityDb.h | 53 +++++++- 2 files changed, 97 insertions(+), 76 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index 624906da36..f33b4f9f58 100644 --- a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -28,7 +28,8 @@ private: enum state_t { ENTRY_FREE, ENTRY_RESERVED, - ENTRY_WRITTEN + ENTRY_WRITTEN, + ENTRY_DISCONNECTED }; struct entry_t { @@ -297,84 +298,18 @@ public: /* list management */ - virtual entry_handle_t open_entry( - BLEProtocol::AddressType_t peer_address_type, - const address_t &peer_address - ) { - const bool peer_address_public = - (peer_address_type == BLEProtocol::AddressType::PUBLIC) || - (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY); - - for (size_t i = 0; i < MAX_ENTRIES; i++) { - entry_t& e = _entries[i]; - - if (e.state == ENTRY_FREE) { - continue; - } else { - if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY && - e.flags.irk_stored == false - ) { - continue; - } - - // lookup for the identity address then the connection address. - if (e.flags.irk_stored && - e.peer_identity.identity_address == peer_address && - e.peer_identity.identity_address_is_public == peer_address_public - ) { - return &e; - // lookup for connection address used during bonding - } else if (e.flags.peer_address == peer_address && - e.flags.peer_address_is_public == peer_address_public - ) { - return &e; - } - } - } - - // determine if the address in input is private or not. - bool is_private_address = false; - if (peer_address_type == BLEProtocol::AddressType::RANDOM) { - ::Gap::RandomAddressType_t random_type(::Gap::RandomAddressType_t::STATIC); - ble_error_t err = ::Gap::getRandomAddressType(peer_address.data(), &random_type); - if (err) { - return NULL; - } - if (random_type != ::Gap::RandomAddressType_t::STATIC) { - is_private_address = true; - } - } - - /* if we din't find one grab the first disconnected slot*/ - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - _entries[i] = entry_t(); - // do not store private addresses in the flags; just store public - // or random static address so it can be reused latter. - if (is_private_address == false) { - _entries[i].flags.peer_address = peer_address; - _entries[i].flags.peer_address_is_public = peer_address_public; - } else { - _entries[i].flags.peer_address = address_t(); - } - _entries[i].state = ENTRY_RESERVED; - return &_entries[i]; - } - } - - return NULL; - } - - virtual void close_entry(entry_handle_t entry_handle) - { + virtual void close_entry(entry_handle_t entry_handle) { entry_t *entry = as_entry(entry_handle); - if (entry && entry->state == ENTRY_RESERVED) { - entry->state = ENTRY_FREE; + if (entry) { + if (entry->state == ENTRY_RESERVED) { + entry->state = ENTRY_FREE; + } else { + entry->state = ENTRY_DISCONNECTED; + } } } - virtual void remove_entry(const address_t peer_identity_address) - { + virtual void remove_entry(const address_t peer_identity_address) { for (size_t i = 0; i < MAX_ENTRIES; i++) { if (_entries[i].state == ENTRY_FREE) { continue; @@ -433,6 +368,41 @@ public: virtual void set_restore(bool reload) { } +private: + virtual uint8_t get_stored_entry_number() { + return MAX_ENTRIES; + } + + virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) { + return &_entries[index % MAX_ENTRIES].flags; + } + + virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) { + return &_entries[index % MAX_ENTRIES].peer_identity; + } + + virtual SecurityDistributionFlags_t* get_free_entry_flags() { + /* get a free one if available */ + for (size_t i = 0; i < MAX_ENTRIES; i++) { + if (_entries[i].state == ENTRY_FREE) { + _entries[i] = entry_t(); + _entries[i].state = ENTRY_RESERVED; + return &_entries[i].flags; + } + } + + /* get any disconnected one */ + for (size_t i = 0; i < MAX_ENTRIES; i++) { + if (_entries[i].state == ENTRY_DISCONNECTED) { + _entries[i] = entry_t(); + _entries[i].state = ENTRY_RESERVED; + return &_entries[i].flags; + } + } + + return NULL; + } + private: entry_t _entries[MAX_ENTRIES]; SecurityEntryIdentity_t _local_identity; diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 41fa81d89b..c76bae52bc 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -363,7 +363,52 @@ public: virtual entry_handle_t open_entry( BLEProtocol::AddressType_t peer_address_type, const address_t &peer_address - ) = 0; + ) { + const bool peer_address_public = + (peer_address_type == BLEProtocol::AddressType::PUBLIC) || + (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY); + + for (size_t i = 0; i < get_stored_entry_number(); i++) { + SecurityDistributionFlags_t* flags = get_stored_entry_flags(i); + + if (flags) { + if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY && + flags->irk_stored == false) { + continue; + } + + /* lookup for connection address used during bonding */ + if (flags->peer_address == peer_address && + flags->peer_address_is_public == peer_address_public) { + return flags; + } + + /* look for the identity address if stored */ + if (flags->irk_stored) { + SecurityEntryIdentity_t* identity = get_stored_entry_identity(i); + + if (identity && + identity->identity_address == peer_address && + identity->identity_address_is_public == peer_address_public) { + return flags; + } + } + + } + } + + SecurityDistributionFlags_t* flags = get_free_entry_flags(); + if (flags) { + /* we need some address to store, so we store even random ones + * this address will be used as an id, possibly replaced later + * by identity address */ + flags->peer_address = peer_address; + flags->peer_address_is_public = peer_address_public; + return flags; + } + + return NULL; + } /** * Close a connection entry. @@ -454,6 +499,12 @@ public: * @param[in] reload if true values will be preserved across resets. */ virtual void set_restore(bool reload) = 0; + +protected: + virtual uint8_t get_stored_entry_number() = 0; + virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) = 0; + virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) = 0; + virtual SecurityDistributionFlags_t* get_free_entry_flags() = 0; }; } /* namespace pal */ From 678d494c5a80a027d9bd37690a16dfe203dbc0ae Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 11 May 2018 10:20:04 +0100 Subject: [PATCH 03/18] init _db pointer --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 8ee91e7096..cb26cc139f 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -240,6 +240,7 @@ public: ) : _pal(palImpl), _connection_monitor(connMonitorImpl), _signing_monitor(signingMonitorImpl), + _db(NULL), _default_authentication(0), _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), @@ -253,6 +254,10 @@ public: _oob_local_random[0] = 1; } + ~GenericSecurityManager() { + delete _db; + } + //////////////////////////////////////////////////////////////////////////// // Helper functions // From a63f38e76761baa48eb6cfce179282fc7beb23ac Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 11 May 2018 19:41:33 +0100 Subject: [PATCH 04/18] moved logic to security db and left storage in memory and file dbs db created at init now --- features/FEATURE_BLE/ble/SecurityManager.h | 2 +- .../FEATURE_BLE/ble/generic/FileSecurityDb.h | 139 +++++++ .../ble/generic/GenericSecurityManager.h | 12 +- .../ble/generic/MemorySecurityDb.h | 357 ++++------------ features/FEATURE_BLE/ble/generic/SecurityDb.h | 383 +++++++++++++----- .../source/generic/FileSecurityDb.cpp | 357 ++++++++++++++++ .../source/generic/GenericSecurityManager.cpp | 53 ++- 7 files changed, 904 insertions(+), 399 deletions(-) create mode 100644 features/FEATURE_BLE/ble/generic/FileSecurityDb.h create mode 100644 features/FEATURE_BLE/source/generic/FileSecurityDb.cpp diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 461858e66f..badc09154c 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -428,7 +428,7 @@ public: SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, bool signing = true, - const uint8_t *dbPath = NULL) { + const char *dbPath = NULL) { /* Avoid compiler warnings about unused variables. */ (void)enableBonding; (void)requireMITM; diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h new file mode 100644 index 0000000000..d345b694db --- /dev/null +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -0,0 +1,139 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GENERIC_FILE_SECURITY_DB_H_ +#define GENERIC_FILE_SECURITY_DB_H_ + +#include "SecurityDb.h" + +#include + +namespace ble { +namespace generic { + +/** Filesystem implementation */ +class FileSecurityDb : public SecurityDb { +private: + + struct entry_t { + SecurityDistributionFlags_t flags; + sign_count_t peer_sign_counter; + size_t file_offset; + }; + + static const size_t MAX_ENTRIES = 5; + + static entry_t* as_entry(entry_handle_t db_handle) + { + return reinterpret_cast(db_handle); + } + +public: + FileSecurityDb(FILE *db_file); + virtual ~FileSecurityDb(); + + /** + * Validates or creates a file for the security database. + * @param db_path path to the file + * @return FILE handle open and ready for use by the database or NULL if unavailable + */ + static FILE* open_db_file(const char *db_path); + + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle + ); + + + /* local keys */ + + /* set */ + virtual void set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k + ); + + virtual void set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ); + + /* peer's keys */ + + /* set */ + + virtual void set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k + ); + + virtual void set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand + ); + + virtual void set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk + ); + + virtual void set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address + ); + + virtual void set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk + ); + + virtual void set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter + ); + + /* saving and loading from nvm */ + + virtual void restore(); + + virtual void sync(); + + virtual void set_restore(bool reload); + +private: + virtual uint8_t get_entry_count(); + + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index); + + virtual void reset_entry(entry_handle_t db_handle); + + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle); + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle); + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle); + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle); + +private: + entry_t _entries[MAX_ENTRIES]; + FILE *_db_file; + static uint8_t _buffer[sizeof(SecurityEntryKeys_t)]; +}; + +} /* namespace pal */ +} /* namespace ble */ + +#endif /*GENERIC_FILE_SECURITY_DB_H_*/ diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index cb26cc139f..4db0911fb7 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -50,7 +50,7 @@ public: SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, bool signing = true, - const uint8_t* db_path = NULL + const char* db_path = NULL ); virtual ble_error_t reset(); @@ -329,24 +329,22 @@ private: * Returns the CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. - * @param[in] csrk connection signature resolving key. + * @param[in] signing connection signature resolving key and counter. */ void return_csrk_cb( SecurityDb::entry_handle_t connection, - const csrk_t *csrk, - sign_count_t sign_counter + const SecurityEntrySigning_t *signing ); /** * Set the peer CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. - * @param[in] csrk connection signature resolving key. + * @param[in] signing connection signature resolving key and counter. */ void set_peer_csrk_cb( SecurityDb::entry_handle_t connection, - const csrk_t *csrk, - sign_count_t sign_counter + const SecurityEntrySigning_t *signing ); /** diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index f33b4f9f58..f1ea0b2534 100644 --- a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef PAL_MEMORY_SECURITY_DB_H_ -#define PAL_MEMORY_SECURITY_DB_H_ +#ifndef GENERIC_MEMORY_SECURITY_DB_H_ +#define GENERIC_MEMORY_SECURITY_DB_H_ #include "SecurityDb.h" @@ -25,121 +25,54 @@ namespace generic { /** Naive memory implementation for verification. */ class MemorySecurityDb : public SecurityDb { private: - enum state_t { - ENTRY_FREE, - ENTRY_RESERVED, - ENTRY_WRITTEN, - ENTRY_DISCONNECTED + struct entry_t { + entry_t() : peer_sign_counter(0) { }; + SecurityDistributionFlags_t flags; + SecurityEntryKeys_t local_keys; + SecurityEntryKeys_t peer_keys; + SecurityEntryIdentity_t peer_identity; + SecurityEntrySigning_t peer_signing; + sign_count_t peer_sign_counter; }; - struct entry_t { - entry_t() : sign_counter(0), state(ENTRY_FREE) { }; - SecurityDistributionFlags_t flags; - SecurityEntryKeys_t peer_keys; - SecurityEntryKeys_t local_keys; - SecurityEntryIdentity_t peer_identity; - csrk_t csrk; - sign_count_t sign_counter; - state_t state; - }; static const size_t MAX_ENTRIES = 5; - static entry_t* as_entry(entry_handle_t entry_handle) + static entry_t* as_entry(entry_handle_t db_handle) { - return reinterpret_cast(entry_handle); + return reinterpret_cast(db_handle); } public: - MemorySecurityDb() : _local_sign_counter(0) { } + MemorySecurityDb() : SecurityDb() { } virtual ~MemorySecurityDb() { } - virtual const SecurityDistributionFlags_t* get_distribution_flags( - entry_handle_t entry_handle + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return NULL; - } - - return &entry->flags; - } - - /** - * Set the distribution flags of the DB entry - */ - virtual void set_distribution_flags( - entry_handle_t entry_handle, - const SecurityDistributionFlags_t& flags - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - entry->state = ENTRY_WRITTEN; - entry->flags = flags; + return reinterpret_cast(db_handle); } /* local keys */ - /* get */ - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle, - const ediv_t &ediv, - const rand_t &rand - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - /* validate we have the correct key */ - if (ediv == entry->local_keys.ediv && rand == entry->local_keys.rand) { - cb(entry_handle, &entry->local_keys); - } else { - cb(entry_handle, NULL); - } - } - - virtual void get_entry_local_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle - ) { - entry_t* entry = as_entry(entry_handle); - if (!entry) { - return; - } - - /* validate we have the correct key */ - if (entry->flags.secure_connections_paired) { - cb(entry_handle, &entry->local_keys); - } else { - cb(entry_handle, NULL); - } - } - - /* set */ virtual void set_entry_local_ltk( - entry_handle_t entry_handle, + entry_handle_t db_handle, const ltk_t <k ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; + entry->flags.ltk_sent = true; entry->local_keys.ltk = ltk; } } virtual void set_entry_local_ediv_rand( - entry_handle_t entry_handle, + entry_handle_t db_handle, const ediv_t &ediv, const rand_t &rand ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; entry->local_keys.ediv = ediv; entry->local_keys.rand = rand; } @@ -147,270 +80,118 @@ public: /* peer's keys */ - /* get */ - virtual void get_entry_peer_csrk( - SecurityEntryCsrkDbCb_t cb, - entry_handle_t entry_handle - ) { - csrk_t csrk; - sign_count_t sign_counter = 0; - entry_t *entry = as_entry(entry_handle); - if (entry) { - csrk = entry->csrk; - sign_counter = entry->sign_counter; - } - cb(entry_handle, &csrk, sign_counter); - } - - virtual void get_entry_peer_keys( - SecurityEntryKeysDbCb_t cb, - entry_handle_t entry_handle - ) { - SecurityEntryKeys_t *key = NULL; - entry_t *entry = as_entry(entry_handle); - if (entry) { - key = &entry->peer_keys; - } - cb(entry_handle, key); - } - - virtual void get_entry_identity( - SecurityEntryIdentityDbCb_t cb, - entry_handle_t entry_handle - ) { - entry_t *entry = as_entry(entry_handle); - if (entry && entry->flags.irk_stored) { - cb(entry_handle, &entry->peer_identity); - } else { - cb(entry_handle, NULL); - } - } - - virtual void get_identity_list( - IdentitylistDbCb_t cb, - ArrayView& entries - ) { - size_t count = 0; - for (size_t i = 0; i < MAX_ENTRIES && count < entries.size(); ++i) { - entry_t& e = _entries[i]; - - if (e.state == ENTRY_WRITTEN && e.flags.irk_stored) { - entries[count] = &e.peer_identity; - ++count; - } - } - - cb(entries, count); - } - /* set */ virtual void set_entry_peer_ltk( - entry_handle_t entry_handle, + entry_handle_t db_handle, const ltk_t <k ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; entry->peer_keys.ltk = ltk; + entry->flags.ltk_stored = true; } } virtual void set_entry_peer_ediv_rand( - entry_handle_t entry_handle, + entry_handle_t db_handle, const ediv_t &ediv, const rand_t &rand ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; entry->peer_keys.ediv = ediv; entry->peer_keys.rand = rand; } } virtual void set_entry_peer_irk( - entry_handle_t entry_handle, + entry_handle_t db_handle, const irk_t &irk ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; entry->peer_identity.irk = irk; entry->flags.irk_stored = true; } } virtual void set_entry_peer_bdaddr( - entry_handle_t entry_handle, + entry_handle_t db_handle, bool address_is_public, const address_t &peer_address ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; entry->peer_identity.identity_address = peer_address; entry->peer_identity.identity_address_is_public = address_is_public; } } virtual void set_entry_peer_csrk( - entry_handle_t entry_handle, + entry_handle_t db_handle, const csrk_t &csrk ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; - entry->csrk = csrk; + entry->flags.csrk_stored = true; + entry->peer_signing.csrk = csrk; } } virtual void set_entry_peer_sign_counter( - entry_handle_t entry_handle, + entry_handle_t db_handle, sign_count_t sign_counter ) { - entry_t *entry = as_entry(entry_handle); + entry_t *entry = as_entry(db_handle); if (entry) { - entry->state = ENTRY_WRITTEN; - entry->sign_counter = sign_counter; + entry->peer_signing.counter = sign_counter; } } - /* local csrk */ - - virtual const csrk_t* get_local_csrk() { - return &_local_csrk; - } - - virtual void set_local_csrk(const csrk_t &csrk) { - _local_csrk = csrk; - } - - virtual sign_count_t get_local_sign_counter() { - return _local_sign_counter; - } - - virtual void set_local_sign_counter( - sign_count_t sign_counter - ) { - _local_sign_counter = sign_counter; - } - - /* list management */ - - virtual void close_entry(entry_handle_t entry_handle) { - entry_t *entry = as_entry(entry_handle); - if (entry) { - if (entry->state == ENTRY_RESERVED) { - entry->state = ENTRY_FREE; - } else { - entry->state = ENTRY_DISCONNECTED; - } - } - } - - virtual void remove_entry(const address_t peer_identity_address) { - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - continue; - } else if (peer_identity_address == _entries[i].peer_identity.identity_address) { - _entries[i] = entry_t(); - _entries[i].state = ENTRY_FREE; - return; - } - } - } - - virtual void clear_entries() { - for (size_t i = 0; i < MAX_ENTRIES; i++) { - _entries[i] = entry_t(); - } - _local_identity = SecurityEntryIdentity_t(); - _local_csrk = csrk_t(); - } - - virtual void get_whitelist(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) { - /*TODO: fill whitelist*/ - cb(whitelist); - } - - virtual void generate_whitelist_from_bond_table(WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist) { - for (size_t i = 0; i < MAX_ENTRIES && i < whitelist->capacity; i++) { - if (_entries[i].flags.peer_address_is_public) { - whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC; - } else { - whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC; - } - - memcpy( - whitelist->addresses[i].address, - _entries[i].peer_identity.identity_address.data(), - sizeof(BLEProtocol::AddressBytes_t) - ); - } - - cb(whitelist); - } - - virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { }; - - virtual void add_whitelist_entry(const address_t &address) { } - - virtual void remove_whitelist_entry(const address_t &address) { } - - virtual void clear_whitelist() { } - - /* saving and loading from nvm */ - - virtual void restore() { } - - virtual void sync() { } - - virtual void set_restore(bool reload) { } - private: - virtual uint8_t get_stored_entry_number() { + virtual uint8_t get_entry_count() { return MAX_ENTRIES; } - virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) { - return &_entries[index % MAX_ENTRIES].flags; - } - - virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) { - return &_entries[index % MAX_ENTRIES].peer_identity; - } - - virtual SecurityDistributionFlags_t* get_free_entry_flags() { - /* get a free one if available */ - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { - _entries[i] = entry_t(); - _entries[i].state = ENTRY_RESERVED; - return &_entries[i].flags; - } + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) { + if (index < MAX_ENTRIES) { + return &_entries[index].flags; + } else { + return NULL; } - - /* get any disconnected one */ - for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_DISCONNECTED) { - _entries[i] = entry_t(); - _entries[i].state = ENTRY_RESERVED; - return &_entries[i].flags; - } - } - - return NULL; } + virtual void reset_entry(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + *entry = entry_t(); + } + + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_identity; + }; + + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_keys; + }; + + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->local_keys; + }; + + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_entry) { + entry_t *entry = reinterpret_cast(db_entry); + return &entry->peer_signing; + }; + private: entry_t _entries[MAX_ENTRIES]; - SecurityEntryIdentity_t _local_identity; - csrk_t _local_csrk; - sign_count_t _local_sign_counter; }; } /* namespace pal */ } /* namespace ble */ -#endif /*PAL_MEMORY_SECURITY_DB_H_*/ +#endif /*GENERIC_MEMORY_SECURITY_DB_H_*/ diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index c76bae52bc..ce5115fdc3 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef PAL_SECURITY_MANAGER_DB_H__ -#define PAL_SECURITY_MANAGER_DB_H__ +#ifndef GENERIC_SECURITY_MANAGER_DB_H__ +#define GENERIC_SECURITY_MANAGER_DB_H__ #include "platform/Callback.h" #include "ble/pal/GapTypes.h" @@ -36,11 +36,15 @@ struct SecurityDistributionFlags_t { encryption_key_size(0), peer_address_is_public(false), csrk_stored(false), - csrk_mitm_protected(false), + csrk_sent(false), ltk_stored(false), + ltk_sent(false), + irk_stored(false), + irk_sent(false), + csrk_mitm_protected(false), ltk_mitm_protected(false), secure_connections_paired(false), - irk_stored(false) { + connected(false) { } /** peer address */ @@ -53,16 +57,21 @@ struct SecurityDistributionFlags_t { /** CSRK (Connection Signature Resolving Key) has been distributed and stored */ uint8_t csrk_stored:1; - /** CSRK that is stored has MITM protection */ - uint8_t csrk_mitm_protected:1; + uint8_t csrk_sent:1; /** LTK (Long Term Key) has been distributed and stored */ uint8_t ltk_stored:1; + uint8_t ltk_sent:1; + /** the security entry has been distributed and stored */ + uint8_t irk_stored:1; + uint8_t irk_sent:1; + + /** CSRK that is stored has MITM protection */ + uint8_t csrk_mitm_protected:1; /** LTK that is stored has MITM protection */ uint8_t ltk_mitm_protected:1; /** the current pairing was done using Secure Connections */ uint8_t secure_connections_paired:1; - /** the security entry has been distributed and stored */ - uint8_t irk_stored:1; + uint8_t connected:1; }; /** Long Term Key and data used to identify it */ @@ -75,6 +84,14 @@ struct SecurityEntryKeys_t { rand_t rand; }; +/** CSRK and sign counter used to verify messages */ +struct SecurityEntrySigning_t { + /** Signing key */ + csrk_t csrk; + /** counter used to verify message to guard from replay attacks */ + sign_count_t counter; +}; + /** Data for resolving random resolvable addresses */ struct SecurityEntryIdentity_t { /** identity address */ @@ -103,8 +120,8 @@ public: typedef mbed::Callback SecurityEntryKeysDbCb_t; - typedef mbed::Callback - SecurityEntryCsrkDbCb_t; + typedef mbed::Callback + SecurityEntrySigningDbCb_t; typedef mbed::Callback SecurityEntryIdentityDbCb_t; typedef mbed::Callback&, size_t count)> @@ -112,30 +129,35 @@ public: typedef mbed::Callback WhitelistDbCb_t; - SecurityDb() { }; + SecurityDb() : _local_sign_counter(0) { }; virtual ~SecurityDb() { }; /** * Return immediately security flags associated to a db entry. * - * @param[in] db_entry Entry of the database queried. + * @param[in] db_handle Entry of the database queried. * @return pointer to the flags or NULL if the entry do not have any * associated flags. */ - virtual const SecurityDistributionFlags_t* get_distribution_flags( - entry_handle_t db_entry + virtual SecurityDistributionFlags_t* get_distribution_flags( + entry_handle_t db_handle ) = 0; /** * Set the distribution flags of a DB entry. * - * @param[in] db_entry Entry of the database that will store the flags. - * @param[in] flags Distribution flags to store in @p db_entry. + * @param[in] db_handle Entry of the database that will store the flags. + * @param[in] flags Distribution flags to store in @p db_handle. */ virtual void set_distribution_flags( - entry_handle_t db_entry, - const SecurityDistributionFlags_t& flags - ) = 0; + entry_handle_t db_handle, + const SecurityDistributionFlags_t& new_flags + ) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags) { + *flags = new_flags; + } + } /* local keys */ @@ -143,49 +165,66 @@ public: * Retrieve stored LTK based on passed in EDIV and RAND values. * * @param[in] cb callback that will receive the LTK struct - * @param[in] db_entry handle of the entry being queried. + * @param[in] db_handle handle of the entry being queried. * @param[in] ediv one of the values used to identify the LTK * @param[in] rand one of the values used to identify the LTK */ virtual void get_entry_local_keys( SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry, + entry_handle_t db_handle, const ediv_t &ediv, const rand_t &rand - ) = 0; + ) { + SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + /* validate we have the correct key */ + if (keys && ediv == keys->ediv && rand == keys->rand) { + cb(db_handle, keys); + } else { + cb(db_handle, NULL); + } + } /** * Retrieve stored LTK generated during secure connections pairing. * * @param[in] cb callback that will receive the LTK struct - * @param[in] db_entry handle of the entry being queried. + * @param[in] db_handle handle of the entry being queried. */ virtual void get_entry_local_keys( SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry - ) = 0; + entry_handle_t db_handle + ) { + SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + /* validate we have the correct key */ + if (flags && keys && flags->secure_connections_paired) { + cb(db_handle, keys); + } else { + cb(db_handle, NULL); + } + } /** * Save new local LTK for a connection. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] ltk the new LTK, if the device is slave, this is the LTK that * will be used when link is encrypted */ virtual void set_entry_local_ltk( - entry_handle_t db_entry, + entry_handle_t db_handle, const ltk_t <k ) = 0; /** * Update EDIV and RAND used to identify the LTK. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] ediv new EDIV value * @param[in] rand new RAND value */ virtual void set_entry_local_ediv_rand( - entry_handle_t db_entry, + entry_handle_t db_handle, const ediv_t &ediv, const rand_t &rand ) = 0; @@ -197,46 +236,52 @@ public: * so that signed packets can be verified. * * @param[in] cb callback which will receive the key - * @param[in] db_entry handle of the entry being queried. + * @param[in] db_handle handle of the entry being queried. */ virtual void get_entry_peer_csrk( - SecurityEntryCsrkDbCb_t cb, - entry_handle_t db_entry - ) = 0; + SecurityEntrySigningDbCb_t cb, + entry_handle_t db_handle + ) { + SecurityEntrySigning_t* signing = read_in_entry_peer_signing(db_handle); + cb(db_handle, signing); + } /** * Return asynchronously the peer encryption key through a callback * so that encryption can be enabled. * * @param[in] cb callback which will receive the key - * @param[in] db_entry handle of the entry being queried. + * @param[in] db_handle handle of the entry being queried. */ virtual void get_entry_peer_keys( SecurityEntryKeysDbCb_t cb, - entry_handle_t db_entry - ) = 0; + entry_handle_t db_handle + ) { + SecurityEntryKeys_t* keys = read_in_entry_peer_keys(db_handle); + cb(db_handle, keys); + } /** * Save new LTK received from the peer. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] ltk the new LTK, if the peer device is slave, this is the LTK * that will be used when link is encrypted */ virtual void set_entry_peer_ltk( - entry_handle_t db_entry, + entry_handle_t db_handle, const ltk_t <k ) = 0; /** * Update EDIV and RAND used to identify the LTK sent by the peer. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] ediv new EDIV value * @param[in] rand new RAND value */ virtual void set_entry_peer_ediv_rand( - entry_handle_t db_entry, + entry_handle_t db_handle, const ediv_t &ediv, const rand_t &rand ) = 0; @@ -244,23 +289,23 @@ public: /** * Update IRK for this connection. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] irk new IRK value */ virtual void set_entry_peer_irk( - entry_handle_t db_entry, + entry_handle_t db_handle, const irk_t &irk ) = 0; /** * Update the identity address of the peer. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] address_is_public is the identity address public or private * @param[in] peer_address the new address */ virtual void set_entry_peer_bdaddr( - entry_handle_t db_entry, + entry_handle_t db_handle, bool address_is_public, const address_t &peer_address ) = 0; @@ -269,12 +314,23 @@ public: * Retrieve stored identity address and IRK. * * @param[in] cb callback that will receive the SecurityEntryIdentity_t struct - * @param[in] db_entry handle of the entry being queried. + * @param[in] db_handle handle of the entry being queried. */ virtual void get_entry_identity( SecurityEntryIdentityDbCb_t cb, - entry_handle_t db_entry - ) = 0; + entry_handle_t db_handle + ) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags && flags->irk_stored) { + SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle); + if (peer_identity) { + cb(db_handle, peer_identity); + return; + } + } + /* avoid duplicate else */ + cb(db_handle, NULL); + } /** * Asynchronously return the identity list stored in NVM through a callback. @@ -288,27 +344,45 @@ public: virtual void get_identity_list( IdentitylistDbCb_t cb, ArrayView& identity_list - ) = 0; + ) { + size_t count = 0; + for (size_t i = 0; i < get_entry_count() && count < identity_list.size(); ++i) { + + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + + if (flags && flags->irk_stored) { + SecurityEntryIdentity_t* peer_identity = read_in_entry_peer_identity(db_handle); + if (peer_identity) { + identity_list[count] = *peer_identity; + count++; + } + } + } + + cb(identity_list, count); + } /** * Update peer signing key. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] csrk new CSRK value */ virtual void set_entry_peer_csrk( - entry_handle_t db_entry, + entry_handle_t db_handle, const csrk_t &csrk ) = 0; /** * Update peer signing counter. * - * @param[in] db_entry handle of the entry being updated. + * @param[in] db_handle handle of the entry being updated. * @param[in] sign_counter new signing counter value */ virtual void set_entry_peer_sign_counter( - entry_handle_t db_entry, + entry_handle_t db_handle, sign_count_t sign_counter ) = 0; @@ -319,14 +393,18 @@ public: * * @return pointer to local CSRK */ - virtual const csrk_t* get_local_csrk() = 0; + virtual const csrk_t* get_local_csrk() { + return &_local_csrk; + } /** * Return local signing counter. * * @return signing counter */ - virtual sign_count_t get_local_sign_counter() = 0; + virtual sign_count_t get_local_sign_counter() { + return _local_sign_counter; + } /** * Update local signing key. @@ -335,7 +413,9 @@ public: */ virtual void set_local_csrk( const csrk_t &csrk - ) = 0; + ) { + _local_csrk = csrk; + } /** * Update local signing counter. @@ -344,7 +424,9 @@ public: */ virtual void set_local_sign_counter( sign_count_t sign_counter - ) = 0; + ) { + _local_sign_counter = sign_counter; + } /* list management */ @@ -363,15 +445,50 @@ public: virtual entry_handle_t open_entry( BLEProtocol::AddressType_t peer_address_type, const address_t &peer_address + ) { + entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); + if (db_handle) { + return db_handle; + } + + SecurityDistributionFlags_t* flags = get_free_entry_flags(); + if (flags) { + const bool peer_address_public = + (peer_address_type == BLEProtocol::AddressType::PUBLIC) || + (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY); + /* we need some address to store, so we store even random ones + * this address will be used as an id, possibly replaced later + * by identity address */ + flags->peer_address = peer_address; + flags->peer_address_is_public = peer_address_public; + return flags; + } + + return NULL; + } + + /** + * Find a database entry based on peer address. + * + * @param[in] peer_address_type type of address + * @param[in] peer_address this address will be used to locate an existing entry. + * + * @return A handle to the entry. + */ + virtual entry_handle_t find_entry_by_peer_address( + BLEProtocol::AddressType_t peer_address_type, + const address_t &peer_address ) { const bool peer_address_public = (peer_address_type == BLEProtocol::AddressType::PUBLIC) || (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY); - for (size_t i = 0; i < get_stored_entry_number(); i++) { - SecurityDistributionFlags_t* flags = get_stored_entry_flags(i); + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); - if (flags) { + /* only look among disconnected entries */ + if (flags && !flags->connected) { if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY && flags->irk_stored == false) { continue; @@ -385,7 +502,7 @@ public: /* look for the identity address if stored */ if (flags->irk_stored) { - SecurityEntryIdentity_t* identity = get_stored_entry_identity(i); + SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle); if (identity && identity->identity_address == peer_address && @@ -393,42 +510,55 @@ public: return flags; } } - } } - SecurityDistributionFlags_t* flags = get_free_entry_flags(); - if (flags) { - /* we need some address to store, so we store even random ones - * this address will be used as an id, possibly replaced later - * by identity address */ - flags->peer_address = peer_address; - flags->peer_address_is_public = peer_address_public; - return flags; - } - return NULL; } /** * Close a connection entry. * - * @param[in] db_entry this handle will be freed up from the security db. + * @param[in] db_handle this handle will be freed up from the security db. */ - virtual void close_entry(entry_handle_t db_entry) = 0; + virtual void close_entry(entry_handle_t db_handle) { + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + if (flags) { + flags->connected = false; + } + sync(); + } /** * Remove entry for this peer from NVM. * - * @param[in] peer_identity_address peer address that no longer needs NVM - * storage. + * @param[in] peer_address_type type of address + * @param[in] peer_address this address will be used to locate an existing + * entry. + * + * @return A handle to the entry. */ - virtual void remove_entry(const address_t peer_identity_address) = 0; + virtual void remove_entry( + BLEProtocol::AddressType_t peer_address_type, + const address_t &peer_address + ) { + entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); + if (db_handle) { + reset_entry(db_handle); + } + } /** * Remove all entries from the security DB. */ - virtual void clear_entries() = 0; + virtual void clear_entries() { + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + reset_entry(db_handle); + } + _local_identity = SecurityEntryIdentity_t(); + _local_csrk = csrk_t(); + } /** * Asynchronously return the whitelist stored in NVM through a callback. @@ -441,7 +571,10 @@ public: virtual void get_whitelist( WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist - ) = 0; + ) { + /*TODO: fill whitelist*/ + cb(whitelist); + } /** * Asynchronously return a whitelist through a callback, generated from the @@ -453,61 +586,127 @@ public: virtual void generate_whitelist_from_bond_table( WhitelistDbCb_t cb, ::Gap::Whitelist_t *whitelist - ) = 0; + ) { + for (size_t i = 0; i < get_entry_count() && i < whitelist->capacity; i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + if (!flags) { + continue; + } + + if (flags->peer_address_is_public) { + whitelist->addresses[i].type = BLEProtocol::AddressType::PUBLIC; + } else { + whitelist->addresses[i].type = BLEProtocol::AddressType::RANDOM_STATIC; + } + + SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle); + if (identity) { + memcpy( + whitelist->addresses[i].address, + identity->identity_address.data(), + sizeof(BLEProtocol::AddressBytes_t) + ); + } + } + + cb(whitelist); + } /** * Update the whitelist stored in NVM by replacing it with new one. * * @param[in] whitelist */ - virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) = 0; + virtual void set_whitelist(const ::Gap::Whitelist_t &whitelist) { }; /** * Add a new entry to the whitelist in the NVM. * * @param[in] address new whitelist entry */ - virtual void add_whitelist_entry(const address_t &address) = 0; + virtual void add_whitelist_entry(const address_t &address) { }; /** * Remove whitelist entry from NVM. * * @param[in] address entry to be removed */ - virtual void remove_whitelist_entry(const address_t &address) = 0; + virtual void remove_whitelist_entry(const address_t &address) { }; /** *Remove all whitelist entries stored in the NVM. */ - virtual void clear_whitelist() = 0; + virtual void clear_whitelist() { }; /* saving and loading from nvm */ /** * Read values from storage. */ - virtual void restore() = 0; + virtual void restore() { }; /** * Flush all values which might be stored in memory into NVM. */ - virtual void sync() = 0; + virtual void sync() { }; /** * Toggle whether values should be preserved across resets. * * @param[in] reload if true values will be preserved across resets. */ - virtual void set_restore(bool reload) = 0; + virtual void set_restore(bool reload) { }; -protected: - virtual uint8_t get_stored_entry_number() = 0; - virtual SecurityDistributionFlags_t* get_stored_entry_flags(uint8_t index) = 0; - virtual SecurityEntryIdentity_t* get_stored_entry_identity(uint8_t index) = 0; - virtual SecurityDistributionFlags_t* get_free_entry_flags() = 0; +private: + virtual SecurityDistributionFlags_t* get_free_entry_flags() { + /* get a free one if available */ + SecurityDistributionFlags_t* match = NULL; + for (size_t i = 0; i < get_entry_count(); i++) { + entry_handle_t db_handle = get_entry_handle_by_index(i); + SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); + + if (flags && !flags->connected) { + /* we settle for any disconnected if we don't find an empty one */ + match = flags; + if (!flags->csrk_stored + && !flags->csrk_sent + && !flags->ltk_stored + && !flags->ltk_sent + && !flags->irk_stored + && !flags->irk_sent) { + /* empty one found, stop looking*/ + break; + } + } + } + + if (match) { + reset_entry(match); + } + + return match; + } + + virtual uint8_t get_entry_count() = 0; + + virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) = 0; + + virtual void reset_entry(entry_handle_t db_handle) = 0; + + virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0; + virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle) = 0; + virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0; + virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0; + +private: + SecurityEntryIdentity_t _local_identity; + csrk_t _local_csrk; + sign_count_t _local_sign_counter; }; } /* namespace pal */ } /* namespace ble */ -#endif /*PAL_SECURITY_MANAGER_DB_H__*/ +#endif /*GENERIC_SECURITY_MANAGER_DB_H__*/ diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp new file mode 100644 index 0000000000..f883dfeebf --- /dev/null +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -0,0 +1,357 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FileSecurityDb.h" + +namespace ble { +namespace generic { + +const uint16_t DB_VERSION = 1; + +#define DB_STORE_OFFSET_LOCAL_KEYS (0) +#define DB_STORE_OFFSET_PEER_KEYS (DB_STORE_OFFSET_LOCAL_KEYS + sizeof(SecurityEntryKeys_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY (DB_STORE_OFFSET_PEER_KEYS + sizeof(SecurityEntryKeys_t)) +#define DB_STORE_OFFSET_PEER_SIGNING (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(SecurityEntryIdentity_t)) +#define DB_SIZE_STORE_PEER_SIGN_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(SecurityEntrySigning_t)) + +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY) +#define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t)) + +#define DB_STORE_OFFSET_PEER_KEYS_LTK (DB_STORE_OFFSET_PEER_KEYS) +#define DB_STORE_OFFSET_PEER_KEYS_EDIV (DB_STORE_OFFSET_PEER_KEYS_LTK + sizeof(ltk_t)) +#define DB_STORE_OFFSET_PEER_KEYS_RAND (DB_STORE_OFFSET_PEER_KEYS_EDIV + sizeof(ediv_t)) + +#define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS) +#define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t)) +#define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t)) + +#define DB_SIZE_STORE \ + (sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryIdentity_t) + \ + sizeof(SecurityEntrySigning_t) + \ + sizeof(sign_count_t)) + +/* without the size of the file offset as we don't store it */ +#define DB_SIZE_ENTRY \ + (sizeof(SecurityDistributionFlags_t) + sizeof(sign_count_t)) + +#define DB_SIZE_ENTRIES \ + (FileSecurityDb::MAX_ENTRIES * DB_SIZE_ENTRY) + +#define DB_SIZE_STORES \ + (FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE) + +#define DB_OFFSET_VERSION (0) +#define DB_OFFSET_RESTORE (DB_OFFSET_VERSION + sizeof(DB_VERSION)) +#define DB_OFFSET_LOCAL_IDENTITY (DB_OFFSET_RESTORE + sizeof(bool)) +#define DB_OFFSET_LOCAL_CSRK (DB_OFFSET_LOCAL_IDENTITY + sizeof(SecurityEntryIdentity_t)) +#define DB_OFFSET_LOCAL_SIGN_COUNT (DB_OFFSET_LOCAL_CSRK + sizeof(csrk_t)) +#define DB_OFFSET_ENTRIES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t)) +#define DB_OFFSET_STORES (DB_OFFSET_ENTRIES + DB_SIZE_ENTRIES) +#define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES) +/* make size multiple of 4 */ +#define DB_SIZE ((((DB_OFFSET_MAX - 1) / 4) * 4) + 4) + +typedef SecurityDb::entry_handle_t entry_handle_t; + +FileSecurityDb::FileSecurityDb(FILE *db_file) + : SecurityDb(), + _db_file(db_file) { + fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); + + /* restore if requested */ + bool restore; + if ((fread(&restore, sizeof(bool), 1, _db_file) == 1) && restore) { + fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET); + fread(&_local_identity, sizeof(_local_identity), 1, _db_file); + + fseek(_db_file, DB_OFFSET_LOCAL_CSRK, SEEK_SET); + fread(&_local_csrk, sizeof(_local_csrk), 1, _db_file); + + fseek(_db_file, DB_OFFSET_LOCAL_SIGN_COUNT, SEEK_SET); + fread(&_local_sign_counter, sizeof(_local_sign_counter), 1, _db_file); + + fseek(_db_file, DB_OFFSET_ENTRIES, SEEK_SET); + /* we read the entries partially and fill the offsets ourselves*/ + for (size_t i = 0; i < get_entry_count(); i++) { + fread(&_entries[i], DB_SIZE_ENTRY, 1, _db_file); + } + } + + /* init the offset in entries so they point to file positions */ + for (size_t i = 0; i < get_entry_count(); i++) { + _entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE; + } +} + +FileSecurityDb::~FileSecurityDb() { + fclose(_db_file); +} + +FILE* FileSecurityDb::open_db_file(const char *db_path) { + FILE *db_file = fopen(db_path, "wb+"); + if (db_file) { + /* we will check the db file and if the version or size doesn't match + * what we expect we will blank it */ + bool init = false; + uint16_t version; + + fseek(db_file, DB_OFFSET_VERSION, SEEK_SET); + + if ((fread(&version, sizeof(version), 1, db_file) == 1) && + (version == DB_VERSION)) { + /* version checks out, try the size */ + fseek(db_file, DB_SIZE - 1, SEEK_SET); + /* read one byte and expect to hit EOF */ + if ((fread(&version, 1, 1, db_file) != 1) || !feof(db_file)) { + init = true; + } + } else { + init = true; + } + + if (init) { + fseek(db_file, 0, SEEK_SET); + + /* zero the file */ + const uint32_t zero = 0; + size_t count = DB_SIZE / 4; + while (count--) { + if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { + fclose(db_file); + return NULL; + } + } + + if (fflush(db_file)) { + fclose(db_file); + return NULL; + } + } + + return db_file; + } + return NULL; +} + +SecurityDistributionFlags_t* FileSecurityDb::get_distribution_flags( + entry_handle_t db_handle +) { + return reinterpret_cast(db_handle); +} + +/* local keys */ + +/* set */ +void FileSecurityDb::set_entry_local_ltk( + entry_handle_t db_handle, + const ltk_t <k +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK, SEEK_SET); + fwrite(<k, sizeof(ltk_t), 1, _db_file); +} + +void FileSecurityDb::set_entry_local_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV, SEEK_SET); + fwrite(&ediv, sizeof(ediv_t), 1, _db_file); + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND, SEEK_SET); + fwrite(&rand, sizeof(rand_t), 1, _db_file); +} + +/* peer's keys */ + +/* set */ + +void FileSecurityDb::set_entry_peer_ltk( + entry_handle_t db_handle, + const ltk_t <k +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK, SEEK_SET); + fwrite(<k, sizeof(ltk_t), 1, _db_file); +} + +void FileSecurityDb::set_entry_peer_ediv_rand( + entry_handle_t db_handle, + const ediv_t &ediv, + const rand_t &rand +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV, SEEK_SET); + fwrite(&ediv, sizeof(ediv_t), 1, _db_file); + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND, SEEK_SET); + fwrite(&rand, sizeof(rand_t), 1, _db_file); +} + +void FileSecurityDb::set_entry_peer_irk( + entry_handle_t db_handle, + const irk_t &irk +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + entry->flags.irk_stored = true; + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK, SEEK_SET); + fwrite(&irk, sizeof(irk_t), 1, _db_file); +} + +void FileSecurityDb::set_entry_peer_bdaddr( + entry_handle_t db_handle, + bool address_is_public, + const address_t &peer_address +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS, SEEK_SET); + fwrite(&peer_address, sizeof(address_t), 1, _db_file); + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC, SEEK_SET); + fwrite(&address_is_public, sizeof(bool), 1, _db_file); +} + +void FileSecurityDb::set_entry_peer_csrk( + entry_handle_t db_handle, + const csrk_t &csrk +) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET); + /* only write in the csrk */ + fwrite(&csrk, sizeof(csrk_t), 1, _db_file); +} + +void FileSecurityDb::set_entry_peer_sign_counter( + entry_handle_t db_handle, + sign_count_t sign_counter +) { + entry_t *entry = as_entry(db_handle); + if (entry) { + entry->peer_sign_counter = sign_counter; + } +} + +/* saving and loading from nvm */ + +void FileSecurityDb::restore() { +} + +void FileSecurityDb::sync() { +} + +void FileSecurityDb::set_restore(bool reload) { +} + +uint8_t FileSecurityDb::get_entry_count() { + return MAX_ENTRIES; +} + +SecurityDistributionFlags_t* FileSecurityDb::get_entry_handle_by_index(uint8_t index) { + if (index < MAX_ENTRIES) { + return &_entries[index].flags; + } else { + return NULL; + } +} + +void FileSecurityDb::reset_entry(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return; + } + entry->flags = SecurityDistributionFlags_t(); + entry->peer_sign_counter = 0; +} + +SecurityEntryIdentity_t* FileSecurityDb::read_in_entry_peer_identity(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY, SEEK_SET); + fread(&_buffer, sizeof(SecurityEntryIdentity_t), 1, _db_file); + return reinterpret_cast(_buffer); +}; + +SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS, SEEK_SET); + fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file); + return reinterpret_cast(_buffer); +}; + +SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS, SEEK_SET); + fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file); + return reinterpret_cast(_buffer); +}; + +SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) { + entry_t *entry = as_entry(db_entry); + if (!entry) { + return NULL; + } + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET); + + /* only read in the csrk */ + fread(&_buffer, sizeof(csrk_t), 1, _db_file); + SecurityEntrySigning_t* signing = reinterpret_cast(_buffer); + /* use the counter held in memory */ + signing->counter = entry->peer_sign_counter; + + return signing; +}; + +} /* namespace pal */ +} /* namespace ble */ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 51878ef678..7a3a43e389 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -40,16 +40,26 @@ ble_error_t GenericSecurityManager::init( SecurityIOCapabilities_t iocaps, const Passkey_t passkey, bool signing, - const uint8_t* db_path + const char* db_path ) { + if (_db) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + ble_error_t err = _pal.initialize(); if (err) { return err; } - _db = new (std::nothrow) MemorySecurityDb(); + FILE* db_file = FileSecurityDb::open_db_file(db_path); + if (db_file) { + _db = new (std::nothrow) FileSecurityDb(db_file); + } else { + _db = new (std::nothrow) MemorySecurityDb(); + } _db->restore(); + _pal.set_io_capability((io_capability_t::type) iocaps); if (passkey) { @@ -99,6 +109,7 @@ ble_error_t GenericSecurityManager::init( } ble_error_t GenericSecurityManager::reset(void) { + MBED_ASSERT(_db); _db->sync(); _pal.reset(); SecurityManager::reset(); @@ -107,6 +118,7 @@ ble_error_t GenericSecurityManager::reset(void) { } ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { + MBED_ASSERT(_db); _db->set_restore(enabled); return BLE_ERROR_NONE; } @@ -116,11 +128,13 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { // ble_error_t GenericSecurityManager::purgeAllBondingState(void) { + MBED_ASSERT(_db); _db->clear_entries(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const { + MBED_ASSERT(_db); if (eventHandler) { _db->generate_whitelist_from_bond_table( mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable), @@ -327,6 +341,7 @@ ble_error_t GenericSecurityManager::enableSigning( connection_handle_t connection, bool enabled ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -468,6 +483,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( // ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -663,6 +679,7 @@ ble_error_t GenericSecurityManager::oobReceived( // ble_error_t GenericSecurityManager::init_signing() { + MBED_ASSERT(_db); const csrk_t *pcsrk = _db->get_local_csrk(); sign_count_t local_sign_counter = _db->get_local_sign_counter(); @@ -712,6 +729,7 @@ ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t c } ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -763,35 +781,33 @@ void GenericSecurityManager::set_ltk_cb( void GenericSecurityManager::set_peer_csrk_cb( SecurityDb::entry_handle_t db_entry, - const csrk_t *csrk, - sign_count_t sign_counter + const SecurityEntrySigning_t* signing ) { ControlBlock_t *cb = get_control_block(db_entry); - if (!cb) { + if (!cb || !signing) { return; } _pal.set_peer_csrk( cb->connection, - *csrk, + signing->csrk, cb->csrk_mitm_protected, - sign_counter + signing->counter ); } void GenericSecurityManager::return_csrk_cb( SecurityDb::entry_handle_t db_entry, - const csrk_t *csrk, - sign_count_t sign_counter + const SecurityEntrySigning_t *signing ) { ControlBlock_t *cb = get_control_block(db_entry); - if (!cb) { + if (!cb || !signing) { return; } eventHandler->signingKey( cb->connection, - csrk, + &signing->csrk, cb->csrk_mitm_protected ); } @@ -838,6 +854,7 @@ void GenericSecurityManager::on_connected( const BLEProtocol::AddressBytes_t local_address, const Gap::ConnectionParams_t *connection_params ) { + MBED_ASSERT(_db); ControlBlock_t *cb = acquire_control_block(connection); if (!cb) { return; @@ -876,6 +893,7 @@ void GenericSecurityManager::on_disconnected( connection_handle_t connection, Gap::DisconnectionReason_t reason ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -994,6 +1012,7 @@ void GenericSecurityManager::on_pairing_timed_out(connection_handle_t connection } void GenericSecurityManager::on_pairing_completed(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (cb) { // set the distribution flags in the db @@ -1022,6 +1041,7 @@ void GenericSecurityManager::on_signed_write_received( connection_handle_t connection, sign_count_t sign_counter ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1055,6 +1075,7 @@ void GenericSecurityManager::on_signed_write_verification_failure( } void GenericSecurityManager::on_signed_write() { + MBED_ASSERT(_db); _db->set_local_sign_counter(_db->get_local_sign_counter() + 1); } @@ -1226,6 +1247,7 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1241,6 +1263,7 @@ void GenericSecurityManager::on_keys_distributed_ltk( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1254,6 +1277,7 @@ void GenericSecurityManager::on_keys_distributed_ediv_rand( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1266,6 +1290,7 @@ void GenericSecurityManager::on_keys_distributed_local_ltk( connection_handle_t connection, const ltk_t <k ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1279,6 +1304,7 @@ void GenericSecurityManager::on_keys_distributed_local_ediv_rand( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1291,6 +1317,7 @@ void GenericSecurityManager::on_keys_distributed_irk( connection_handle_t connection, const irk_t &irk ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1304,6 +1331,7 @@ void GenericSecurityManager::on_keys_distributed_bdaddr( advertising_peer_address_type_t peer_address_type, const address_t &peer_identity_address ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1320,6 +1348,7 @@ void GenericSecurityManager::on_keys_distributed_csrk( connection_handle_t connection, const csrk_t &csrk ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1341,6 +1370,7 @@ void GenericSecurityManager::on_ltk_request( const ediv_t &ediv, const rand_t &rand ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1379,6 +1409,7 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; From 3af4d0b50f929d40cfca7d01a95dbae65d04f01d Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 11 May 2018 19:52:12 +0100 Subject: [PATCH 05/18] get identity list function argument needs to have its own memory allocated --- features/FEATURE_BLE/ble/generic/FileSecurityDb.h | 2 +- .../ble/generic/GenericSecurityManager.h | 2 +- features/FEATURE_BLE/ble/generic/SecurityDb.h | 6 +++--- .../source/generic/GenericSecurityManager.cpp | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index d345b694db..7268b2708e 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -130,7 +130,7 @@ private: private: entry_t _entries[MAX_ENTRIES]; FILE *_db_file; - static uint8_t _buffer[sizeof(SecurityEntryKeys_t)]; + uint8_t _buffer[sizeof(SecurityEntryKeys_t)]; }; } /* namespace pal */ diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 4db0911fb7..a8b726fee7 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -421,7 +421,7 @@ private: * @param count Number of identities entries retrieved. */ void on_identity_list_retrieved( - ble::ArrayView& identity_list, + ble::ArrayView& identity_list, size_t count ); diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index ce5115fdc3..93a8419e8c 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -124,7 +124,7 @@ public: SecurityEntrySigningDbCb_t; typedef mbed::Callback SecurityEntryIdentityDbCb_t; - typedef mbed::Callback&, size_t count)> + typedef mbed::Callback&, size_t count)> IdentitylistDbCb_t; typedef mbed::Callback WhitelistDbCb_t; @@ -343,7 +343,7 @@ public: */ virtual void get_identity_list( IdentitylistDbCb_t cb, - ArrayView& identity_list + ArrayView& identity_list ) { size_t count = 0; for (size_t i = 0; i < get_entry_count() && count < identity_list.size(); ++i) { @@ -700,7 +700,7 @@ private: virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0; virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0; -private: +protected: SecurityEntryIdentity_t _local_identity; csrk_t _local_csrk; sign_count_t _local_sign_counter; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 7a3a43e389..a8fb9a7679 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -90,11 +90,11 @@ ble_error_t GenericSecurityManager::init( _pal.set_event_handler(this); uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity(); - SecurityEntryIdentity_t** identity_list_p = - new (std::nothrow) SecurityEntryIdentity_t*[resolving_list_capacity]; + SecurityEntryIdentity_t* identity_list_p = + new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity]; if (identity_list_p) { - ArrayView identity_list( + ArrayView identity_list( identity_list_p, resolving_list_capacity ); @@ -925,7 +925,7 @@ void GenericSecurityManager::on_security_entry_retrieved( } void GenericSecurityManager::on_identity_list_retrieved( - ble::ArrayView& identity_list, + ble::ArrayView& identity_list, size_t count ) { typedef advertising_peer_address_type_t address_type_t; @@ -933,11 +933,11 @@ void GenericSecurityManager::on_identity_list_retrieved( _pal.clear_resolving_list(); for (size_t i = 0; i < count; ++i) { _pal.add_device_to_resolving_list( - identity_list[i]->identity_address_is_public ? + identity_list[i].identity_address_is_public ? address_type_t::PUBLIC_ADDRESS : address_type_t::RANDOM_ADDRESS, - identity_list[i]->identity_address, - identity_list[i]->irk + identity_list[i].identity_address, + identity_list[i].irk ); } From ab117737fa5e5296b75ceadf39cea1bb4865b3c6 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Sun, 13 May 2018 22:55:47 +0100 Subject: [PATCH 06/18] write back counter, sync entry by hand;e --- .../FEATURE_BLE/ble/generic/FileSecurityDb.h | 5 ++-- .../ble/generic/MemorySecurityDb.h | 3 +-- features/FEATURE_BLE/ble/generic/SecurityDb.h | 5 ++-- .../source/generic/FileSecurityDb.cpp | 24 ++++++++++++------- .../source/generic/GenericSecurityManager.cpp | 4 ---- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index 7268b2708e..62cf6fcc48 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -36,8 +36,7 @@ private: static const size_t MAX_ENTRIES = 5; - static entry_t* as_entry(entry_handle_t db_handle) - { + static entry_t* as_entry(entry_handle_t db_handle) { return reinterpret_cast(db_handle); } @@ -111,7 +110,7 @@ public: virtual void restore(); - virtual void sync(); + virtual void sync(entry_handle_t db_handle); virtual void set_restore(bool reload); diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index f1ea0b2534..6ca9c3b3b0 100644 --- a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -26,13 +26,12 @@ namespace generic { class MemorySecurityDb : public SecurityDb { private: struct entry_t { - entry_t() : peer_sign_counter(0) { }; + entry_t() { }; SecurityDistributionFlags_t flags; SecurityEntryKeys_t local_keys; SecurityEntryKeys_t peer_keys; SecurityEntryIdentity_t peer_identity; SecurityEntrySigning_t peer_signing; - sign_count_t peer_sign_counter; }; static const size_t MAX_ENTRIES = 5; diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 93a8419e8c..0186205c23 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -86,6 +86,7 @@ struct SecurityEntryKeys_t { /** CSRK and sign counter used to verify messages */ struct SecurityEntrySigning_t { + SecurityEntrySigning_t() : counter(0) { }; /** Signing key */ csrk_t csrk; /** counter used to verify message to guard from replay attacks */ @@ -526,7 +527,7 @@ public: if (flags) { flags->connected = false; } - sync(); + sync(db_handle); } /** @@ -650,7 +651,7 @@ public: /** * Flush all values which might be stored in memory into NVM. */ - virtual void sync() { }; + virtual void sync(entry_handle_t db_handle) { }; /** * Toggle whether values should be preserved across resets. diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index f883dfeebf..e2698d6c9d 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -25,19 +25,20 @@ const uint16_t DB_VERSION = 1; #define DB_STORE_OFFSET_PEER_KEYS (DB_STORE_OFFSET_LOCAL_KEYS + sizeof(SecurityEntryKeys_t)) #define DB_STORE_OFFSET_PEER_IDENTITY (DB_STORE_OFFSET_PEER_KEYS + sizeof(SecurityEntryKeys_t)) #define DB_STORE_OFFSET_PEER_SIGNING (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(SecurityEntryIdentity_t)) -#define DB_SIZE_STORE_PEER_SIGN_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(SecurityEntrySigning_t)) -#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY) -#define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t)) -#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t)) +#define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS) +#define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t)) +#define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t)) #define DB_STORE_OFFSET_PEER_KEYS_LTK (DB_STORE_OFFSET_PEER_KEYS) #define DB_STORE_OFFSET_PEER_KEYS_EDIV (DB_STORE_OFFSET_PEER_KEYS_LTK + sizeof(ltk_t)) #define DB_STORE_OFFSET_PEER_KEYS_RAND (DB_STORE_OFFSET_PEER_KEYS_EDIV + sizeof(ediv_t)) -#define DB_STORE_OFFSET_LOCAL_KEYS_LTK (DB_STORE_OFFSET_LOCAL_KEYS) -#define DB_STORE_OFFSET_LOCAL_KEYS_EDIV (DB_STORE_OFFSET_LOCAL_KEYS_LTK + sizeof(ltk_t)) -#define DB_STORE_OFFSET_LOCAL_KEYS_RAND (DB_STORE_OFFSET_LOCAL_KEYS_EDIV + sizeof(ediv_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS (DB_STORE_OFFSET_PEER_IDENTITY) +#define DB_STORE_OFFSET_PEER_IDENTITY_IRK (DB_STORE_OFFSET_PEER_IDENTITY + sizeof(address_t)) +#define DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC (DB_STORE_OFFSET_PEER_IDENTITY_IRK + sizeof(irk_t)) + +#define DB_STORE_OFFSET_PEER_SIGNING_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(csrk_t)) #define DB_SIZE_STORE \ (sizeof(SecurityEntryKeys_t) + \ @@ -280,7 +281,14 @@ void FileSecurityDb::set_entry_peer_sign_counter( void FileSecurityDb::restore() { } -void FileSecurityDb::sync() { +void FileSecurityDb::sync(entry_handle_t db_handle) { + entry_t *entry = as_entry(db_handle); + if (!entry) { + return; + } + + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT, SEEK_SET); + fwrite(&entry->peer_sign_counter, sizeof(sign_count_t), 1, _db_file); } void FileSecurityDb::set_restore(bool reload) { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a8fb9a7679..b8d6a85a78 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -109,8 +109,6 @@ ble_error_t GenericSecurityManager::init( } ble_error_t GenericSecurityManager::reset(void) { - MBED_ASSERT(_db); - _db->sync(); _pal.reset(); SecurityManager::reset(); @@ -901,8 +899,6 @@ void GenericSecurityManager::on_disconnected( _db->close_entry(cb->db_entry); release_control_block(cb); - - _db->sync(); } void GenericSecurityManager::on_security_entry_retrieved( From 23c6a69d66d775e45b6d707858fff05c11d16c9c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Sun, 13 May 2018 23:26:34 +0100 Subject: [PATCH 07/18] key dist flags only in db now and not in control block of sec manager --- .../ble/generic/GenericSecurityManager.h | 2 +- .../source/generic/GenericSecurityManager.cpp | 197 +++++++++++++----- 2 files changed, 147 insertions(+), 52 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index a8b726fee7..f5f060a5e6 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -426,7 +426,7 @@ private: ); private: - struct ControlBlock_t : public SecurityDistributionFlags_t { + struct ControlBlock_t { ControlBlock_t(); pal::KeyDistribution get_initiator_key_distribution() { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index b8d6a85a78..ccb4cc5bcf 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -345,11 +345,16 @@ ble_error_t GenericSecurityManager::enableSigning( return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + cb->signing_override_default = true; if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { cb->signing_requested = true; - if (cb->csrk_stored) { + if (flags->csrk_stored) { /* used the stored ones when available */ _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), @@ -390,8 +395,13 @@ ble_error_t GenericSecurityManager::getLinkEncryption( return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + if (cb->encrypted) { - if (cb->ltk_mitm_protected || cb->mitm_performed) { + if (flags->ltk_mitm_protected || cb->mitm_performed) { *encryption = link_encryption_t::ENCRYPTED_WITH_MITM; } else { *encryption = link_encryption_t::ENCRYPTED; @@ -414,6 +424,11 @@ ble_error_t GenericSecurityManager::setLinkEncryption( return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + link_encryption_t current_encryption(link_encryption_t::NOT_ENCRYPTED); getLinkEncryption(connection, ¤t_encryption); @@ -439,7 +454,7 @@ ble_error_t GenericSecurityManager::setLinkEncryption( } else if (encryption == link_encryption_t::ENCRYPTED_WITH_MITM) { - if (cb->ltk_mitm_protected && !cb->encrypted) { + if (flags->ltk_mitm_protected && !cb->encrypted) { cb->encryption_requested = true; return enable_encryption(connection); } else { @@ -461,12 +476,17 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize( uint8_t *size ) { ControlBlock_t *cb = get_control_block(connection); - if (cb) { - *size = cb->encryption_key_size; - return BLE_ERROR_NONE; - } else { + if (!cb) { return BLE_ERROR_INVALID_PARAM; } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + *size = flags->encryption_key_size; + return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( @@ -487,7 +507,12 @@ ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection return BLE_ERROR_INVALID_PARAM; } - if (cb->csrk_stored && (cb->csrk_mitm_protected || !authenticated)) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + if (flags->csrk_stored && (flags->csrk_mitm_protected || !authenticated)) { /* we have a key that is either authenticated or we don't care if it is * so retrieve it from the db now */ _db->get_entry_peer_csrk( @@ -527,7 +552,12 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co return BLE_ERROR_INVALID_PARAM; } - if (cb->ltk_mitm_protected) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + + if (flags->ltk_mitm_protected) { if (cb->authenticated) { return BLE_ERROR_NONE; } else { @@ -639,10 +669,15 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( return BLE_ERROR_INVALID_PARAM; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + _oob_temporary_key = *tk; _oob_temporary_key_creator_address = *address; - if (cb->peer_address == _oob_temporary_key_creator_address) { + if (flags->peer_address == _oob_temporary_key_creator_address) { cb->attempt_oob = true; } @@ -732,8 +767,14 @@ ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connec if (!cb) { return BLE_ERROR_INVALID_PARAM; } + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return BLE_ERROR_INVALID_PARAM; + } + if (cb->is_master) { - if (cb->ltk_stored) { + if (flags->ltk_stored) { _db->get_entry_peer_keys( mbed::callback(this, &GenericSecurityManager::enable_encryption_cb), cb->db_entry @@ -752,12 +793,20 @@ void GenericSecurityManager::enable_encryption_cb( const SecurityEntryKeys_t* entryKeys ) { ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } - if (cb && entryKeys) { - if (cb->secure_connections_paired) { - _pal.enable_encryption(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (entryKeys) { + if (flags->secure_connections_paired) { + _pal.enable_encryption(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected); } else { - _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, cb->ltk_mitm_protected); + _pal.enable_encryption(cb->connection, entryKeys->ltk, entryKeys->rand, entryKeys->ediv, flags->ltk_mitm_protected); } } } @@ -767,13 +816,19 @@ void GenericSecurityManager::set_ltk_cb( const SecurityEntryKeys_t* entryKeys ) { ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } - if (cb) { - if (entryKeys) { - _pal.set_ltk(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected, cb->secure_connections_paired); - } else { - _pal.set_ltk_not_found(cb->connection); - } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (entryKeys) { + _pal.set_ltk(cb->connection, entryKeys->ltk, flags->ltk_mitm_protected, flags->secure_connections_paired); + } else { + _pal.set_ltk_not_found(cb->connection); } } @@ -786,10 +841,15 @@ void GenericSecurityManager::set_peer_csrk_cb( return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + _pal.set_peer_csrk( cb->connection, signing->csrk, - cb->csrk_mitm_protected, + flags->csrk_mitm_protected, signing->counter ); } @@ -803,10 +863,15 @@ void GenericSecurityManager::return_csrk_cb( return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + eventHandler->signingKey( cb->connection, &signing->csrk, - cb->csrk_mitm_protected + flags->csrk_mitm_protected ); } @@ -816,15 +881,20 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + /* if we support secure connection we only care about secure connections oob data */ if (_default_authentication.get_secure_connections()) { - cb->oob_present = (cb->peer_address == _oob_peer_address); + cb->oob_present = (flags->peer_address == _oob_peer_address); } else { /* otherwise for legacy pairing we first set the oob based on set preference */ cb->oob_present = cb->attempt_oob; /* and also turn it on if we have oob data for legacy pairing */ - if (cb->peer_address == _oob_temporary_key_creator_address + if (flags->peer_address == _oob_temporary_key_creator_address || cb->local_address == _oob_temporary_key_creator_address) { cb->oob_present = true; } @@ -859,27 +929,22 @@ void GenericSecurityManager::on_connected( } // setup the control block - cb->peer_address = peer_address; cb->local_address = local_address; - cb->peer_address_is_public = - (peer_address_type == BLEProtocol::AddressType::PUBLIC); cb->is_master = (role == Gap::CENTRAL); // get the associated db handle and the distribution flags if any cb->db_entry = _db->open_entry(peer_address_type, peer_address); - const SecurityDistributionFlags_t* dist_flags = - _db->get_distribution_flags(cb->db_entry); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); - if (dist_flags) { - *static_cast(cb) = *dist_flags; - } + flags->peer_address = peer_address; + flags->peer_address_is_public = (peer_address_type == BLEProtocol::AddressType::PUBLIC); const bool signing = cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing(); - if (signing && cb->csrk_stored) { + if (signing && flags->csrk_stored) { _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), cb->db_entry @@ -1011,8 +1076,6 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t connection MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (cb) { - // set the distribution flags in the db - _db->set_distribution_flags(cb->db_entry, *cb); _db->get_entry_identity( mbed::callback(this, &GenericSecurityManager::on_security_entry_retrieved), cb->db_entry @@ -1084,14 +1147,19 @@ void GenericSecurityManager::on_slave_security_request( return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + bool pairing_required = false; - if (authentication.get_secure_connections() && !cb->secure_connections_paired + if (authentication.get_secure_connections() && !flags->secure_connections_paired && _default_authentication.get_secure_connections()) { pairing_required = true; } - if (authentication.get_mitm() && !cb->ltk_mitm_protected) { + if (authentication.get_mitm() && !flags->ltk_mitm_protected) { pairing_required = true; cb->mitm_requested = true; } @@ -1193,7 +1261,12 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle return; } - if (cb->peer_address == _oob_peer_address) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (flags->peer_address == _oob_peer_address) { _pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm); /* do not re-use peer OOB */ set_all_zeros(_oob_peer_address); @@ -1208,14 +1281,19 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c return; } - if (cb->peer_address == _oob_temporary_key_creator_address + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (flags->peer_address == _oob_temporary_key_creator_address || cb->local_address == _oob_temporary_key_creator_address) { set_mitm_performed(connection); _pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key); /* do not re-use peer OOB */ - if (cb->peer_address == _oob_temporary_key_creator_address) { + if (flags->peer_address == _oob_temporary_key_creator_address) { set_all_zeros(_oob_temporary_key_creator_address); } @@ -1249,8 +1327,13 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( return; } - cb->ltk_mitm_protected = cb->mitm_performed; - cb->secure_connections_paired = true; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->ltk_mitm_protected = cb->mitm_performed; + flags->secure_connections_paired = true; _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1264,7 +1347,13 @@ void GenericSecurityManager::on_keys_distributed_ltk( if (!cb) { return; } - cb->ltk_mitm_protected = cb->mitm_performed; + + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->ltk_mitm_protected = cb->mitm_performed; _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1350,14 +1439,19 @@ void GenericSecurityManager::on_keys_distributed_csrk( return; } - cb->csrk_mitm_protected = cb->mitm_performed; + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->csrk_mitm_protected = cb->mitm_performed; _db->set_entry_peer_csrk(cb->db_entry, csrk); eventHandler->signingKey( connection, &csrk, - cb->csrk_mitm_protected + flags->csrk_mitm_protected ); } @@ -1383,7 +1477,6 @@ void GenericSecurityManager::on_ltk_request( /* control blocks list management */ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : - SecurityDistributionFlags_t(), connection(0), db_entry(0), local_address(), @@ -1450,10 +1543,12 @@ GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_bloc const address_t &peer_address ) { for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { - if (!_control_blocks[i].connected) { - continue; - } else if (peer_address == _control_blocks[i].peer_address) { - return &_control_blocks[i]; + ControlBlock_t *cb = &_control_blocks[i]; + if (cb->connected) { + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (flags && (flags->peer_address == peer_address)) { + return cb; + } } } return NULL; From 8f90875cd6f564f439c4cfbb748bfd2d2f77c8cb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Sun, 13 May 2018 23:49:27 +0100 Subject: [PATCH 08/18] reset entry now remove old keys --- .../source/generic/FileSecurityDb.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index e2698d6c9d..1181a1455c 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -40,8 +40,11 @@ const uint16_t DB_VERSION = 1; #define DB_STORE_OFFSET_PEER_SIGNING_COUNT (DB_STORE_OFFSET_PEER_SIGNING + sizeof(csrk_t)) +/* make size multiple of 4 */ +#define PAD4(value) ((((value - 1) / 4) * 4) + 4) + #define DB_SIZE_STORE \ - (sizeof(SecurityEntryKeys_t) + \ + PAD4(sizeof(SecurityEntryKeys_t) + \ sizeof(SecurityEntryKeys_t) + \ sizeof(SecurityEntryIdentity_t) + \ sizeof(SecurityEntrySigning_t) + \ @@ -65,8 +68,7 @@ const uint16_t DB_VERSION = 1; #define DB_OFFSET_ENTRIES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t)) #define DB_OFFSET_STORES (DB_OFFSET_ENTRIES + DB_SIZE_ENTRIES) #define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES) -/* make size multiple of 4 */ -#define DB_SIZE ((((DB_OFFSET_MAX - 1) / 4) * 4) + 4) +#define DB_SIZE PAD4(DB_OFFSET_MAX) typedef SecurityDb::entry_handle_t entry_handle_t; @@ -311,6 +313,14 @@ void FileSecurityDb::reset_entry(entry_handle_t db_entry) { if (!entry) { return; } + + fseek(_db_file, entry->file_offset, SEEK_SET); + const uint32_t zero = 0; + size_t count = DB_SIZE_STORE / 4; + while (count--) { + fwrite(&zero, sizeof(zero), 1, _db_file); + } + entry->flags = SecurityDistributionFlags_t(); entry->peer_sign_counter = 0; } From d3524e240797a8533413ff18e4d608dd3a3ee88c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Sun, 13 May 2018 23:49:44 +0100 Subject: [PATCH 09/18] doxygen --- features/FEATURE_BLE/ble/generic/SecurityDb.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 0186205c23..4b181fe0a8 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -661,6 +661,11 @@ public: virtual void set_restore(bool reload) { }; private: + /** + * Get an entry for a new connection not present in the db yet. This will find a free entry + * or use a disconnected entry by reseting all the stored information. + * @return empty entry for the new connection + */ virtual SecurityDistributionFlags_t* get_free_entry_flags() { /* get a free one if available */ SecurityDistributionFlags_t* match = NULL; @@ -690,10 +695,23 @@ private: return match; } + /** + * How many entries can be stored in the databes. + * @return max number of entries + */ virtual uint8_t get_entry_count() = 0; + /** + * Return database entry based on its index. + * @param index index from 0 to get_entry_count() + * @return databse entry stored at index + */ virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) = 0; + /** + * Delete all the information. + * @param db_handle handle for the entry to be reset + */ virtual void reset_entry(entry_handle_t db_handle) = 0; virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0; From a7f8d547613a1b4fb5f6792bd13b29c1ab7c7ce8 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Sun, 13 May 2018 23:54:44 +0100 Subject: [PATCH 10/18] more doxygen --- features/FEATURE_BLE/ble/generic/SecurityDb.h | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 4b181fe0a8..c4b7969f4a 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -714,9 +714,36 @@ private: */ virtual void reset_entry(entry_handle_t db_handle) = 0; + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ virtual SecurityEntryIdentity_t* read_in_entry_peer_identity(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ virtual SecurityEntryKeys_t* read_in_entry_peer_keys(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle) = 0; + + /** + * This will read in the requested information into a buffer that will remain valid + * until another read_in call is made. + * @param db_handle handle of the entry to be read + * @return pointer to buffer holding the query result, NULL when not found + */ virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle) = 0; protected: From f4f3a3c697dfbef212b9dae86e8fba7c871b5a81 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 14 May 2018 09:52:49 +0100 Subject: [PATCH 11/18] store ltk and csrk but not irk sent status and missing asserts --- features/FEATURE_BLE/ble/generic/SecurityDb.h | 6 +-- .../source/generic/GenericSecurityManager.cpp | 49 ++++++++++++++++--- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index c4b7969f4a..f24ad0b09e 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -40,7 +40,6 @@ struct SecurityDistributionFlags_t { ltk_stored(false), ltk_sent(false), irk_stored(false), - irk_sent(false), csrk_mitm_protected(false), ltk_mitm_protected(false), secure_connections_paired(false), @@ -63,7 +62,6 @@ struct SecurityDistributionFlags_t { uint8_t ltk_sent:1; /** the security entry has been distributed and stored */ uint8_t irk_stored:1; - uint8_t irk_sent:1; /** CSRK that is stored has MITM protection */ uint8_t csrk_mitm_protected:1; @@ -677,11 +675,9 @@ private: /* we settle for any disconnected if we don't find an empty one */ match = flags; if (!flags->csrk_stored - && !flags->csrk_sent && !flags->ltk_stored && !flags->ltk_sent - && !flags->irk_stored - && !flags->irk_sent) { + && !flags->irk_stored) { /* empty one found, stop looking*/ break; } diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index ccb4cc5bcf..96b2385dfc 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -354,7 +354,7 @@ ble_error_t GenericSecurityManager::enableSigning( if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { cb->signing_requested = true; - if (flags->csrk_stored) { + if (flags->csrk_stored && flags->csrk_sent) { /* used the stored ones when available */ _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), @@ -389,7 +389,7 @@ ble_error_t GenericSecurityManager::getLinkEncryption( connection_handle_t connection, link_encryption_t *encryption ) { - + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -419,6 +419,7 @@ ble_error_t GenericSecurityManager::setLinkEncryption( connection_handle_t connection, link_encryption_t encryption ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -475,6 +476,7 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize( connection_handle_t connection, uint8_t *size ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -547,6 +549,7 @@ ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in // ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -663,6 +666,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( const address_t *address, const oob_tk_t *tk ) { + MBED_ASSERT(_db); if (address && tk) { ControlBlock_t *cb = get_control_block(*address); if (!cb) { @@ -792,6 +796,7 @@ void GenericSecurityManager::enable_encryption_cb( SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { return; @@ -815,6 +820,7 @@ void GenericSecurityManager::set_ltk_cb( SecurityDb::entry_handle_t db_entry, const SecurityEntryKeys_t* entryKeys ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { return; @@ -858,6 +864,7 @@ void GenericSecurityManager::return_csrk_cb( SecurityDb::entry_handle_t db_entry, const SecurityEntrySigning_t *signing ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(db_entry); if (!cb || !signing) { return; @@ -876,6 +883,7 @@ void GenericSecurityManager::return_csrk_cb( } void GenericSecurityManager::update_oob_presence(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1142,6 +1150,7 @@ void GenericSecurityManager::on_slave_security_request( connection_handle_t connection, AuthenticationMask authentication ) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1276,6 +1285,7 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle } void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { + MBED_ASSERT(_db); ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -1334,6 +1344,7 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( flags->ltk_mitm_protected = cb->mitm_performed; flags->secure_connections_paired = true; + flags->ltk_stored = true; _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1354,6 +1365,7 @@ void GenericSecurityManager::on_keys_distributed_ltk( } flags->ltk_mitm_protected = cb->mitm_performed; + flags->ltk_stored = true; _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1381,6 +1393,12 @@ void GenericSecurityManager::on_keys_distributed_local_ltk( return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->ltk_sent = true; _db->set_entry_local_ltk(cb->db_entry, ltk); } @@ -1408,6 +1426,12 @@ void GenericSecurityManager::on_keys_distributed_irk( return; } + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + flags->irk_stored = true; _db->set_entry_peer_irk(cb->db_entry, irk); } @@ -1445,6 +1469,7 @@ void GenericSecurityManager::on_keys_distributed_csrk( } flags->csrk_mitm_protected = cb->mitm_performed; + flags->csrk_stored = true; _db->set_entry_peer_csrk(cb->db_entry, csrk); @@ -1466,12 +1491,19 @@ void GenericSecurityManager::on_ltk_request( return; } - _db->get_entry_local_keys( - mbed::callback(this, &GenericSecurityManager::set_ltk_cb), - cb->db_entry, - ediv, - rand - ); + SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); + if (!flags) { + return; + } + + if (flags->ltk_stored) { + _db->get_entry_local_keys( + mbed::callback(this, &GenericSecurityManager::set_ltk_cb), + cb->db_entry, + ediv, + rand + ); + } } /* control blocks list management */ @@ -1542,6 +1574,7 @@ GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_bloc GenericSecurityManager::ControlBlock_t* GenericSecurityManager::get_control_block( const address_t &peer_address ) { + MBED_ASSERT(_db); for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { ControlBlock_t *cb = &_control_blocks[i]; if (cb->connected) { From 579cb5e2227b08fe48569e674a8df1853146e2a4 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 14 May 2018 10:26:44 +0100 Subject: [PATCH 12/18] avoid setting flags twice --- features/FEATURE_BLE/ble/generic/SecurityDb.h | 2 -- features/FEATURE_BLE/source/generic/FileSecurityDb.cpp | 6 ++++++ .../source/generic/GenericSecurityManager.cpp | 9 ++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index f24ad0b09e..009d769554 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -36,7 +36,6 @@ struct SecurityDistributionFlags_t { encryption_key_size(0), peer_address_is_public(false), csrk_stored(false), - csrk_sent(false), ltk_stored(false), ltk_sent(false), irk_stored(false), @@ -56,7 +55,6 @@ struct SecurityDistributionFlags_t { /** CSRK (Connection Signature Resolving Key) has been distributed and stored */ uint8_t csrk_stored:1; - uint8_t csrk_sent:1; /** LTK (Long Term Key) has been distributed and stored */ uint8_t ltk_stored:1; uint8_t ltk_sent:1; diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 1181a1455c..76fedd8262 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -170,6 +170,8 @@ void FileSecurityDb::set_entry_local_ltk( return; } + entry->flags.ltk_sent = true; + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK, SEEK_SET); fwrite(<k, sizeof(ltk_t), 1, _db_file); } @@ -203,6 +205,8 @@ void FileSecurityDb::set_entry_peer_ltk( return; } + entry->flags.ltk_stored = true; + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK, SEEK_SET); fwrite(<k, sizeof(ltk_t), 1, _db_file); } @@ -263,6 +267,8 @@ void FileSecurityDb::set_entry_peer_csrk( return; } + entry->flags.csrk_stored = true; + fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET); /* only write in the csrk */ fwrite(&csrk, sizeof(csrk_t), 1, _db_file); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 96b2385dfc..655bd2f88a 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -354,7 +354,7 @@ ble_error_t GenericSecurityManager::enableSigning( if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { cb->signing_requested = true; - if (flags->csrk_stored && flags->csrk_sent) { + if (flags->csrk_stored) { /* used the stored ones when available */ _db->get_entry_peer_csrk( mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), @@ -1344,7 +1344,6 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( flags->ltk_mitm_protected = cb->mitm_performed; flags->secure_connections_paired = true; - flags->ltk_stored = true; _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1365,7 +1364,7 @@ void GenericSecurityManager::on_keys_distributed_ltk( } flags->ltk_mitm_protected = cb->mitm_performed; - flags->ltk_stored = true; + _db->set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1398,7 +1397,6 @@ void GenericSecurityManager::on_keys_distributed_local_ltk( return; } - flags->ltk_sent = true; _db->set_entry_local_ltk(cb->db_entry, ltk); } @@ -1431,7 +1429,6 @@ void GenericSecurityManager::on_keys_distributed_irk( return; } - flags->irk_stored = true; _db->set_entry_peer_irk(cb->db_entry, irk); } @@ -1469,8 +1466,6 @@ void GenericSecurityManager::on_keys_distributed_csrk( } flags->csrk_mitm_protected = cb->mitm_performed; - flags->csrk_stored = true; - _db->set_entry_peer_csrk(cb->db_entry, csrk); eventHandler->signingKey( From f8244a3d87b48fe38064f50f30e79cd3d3e5d702 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 15 May 2018 10:24:59 +0100 Subject: [PATCH 13/18] review comments, init partly moved to restore, restore setting enabled, null check on filepath --- .../source/generic/FileSecurityDb.cpp | 104 ++++++++++-------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 76fedd8262..1b8c0357c9 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -78,21 +78,10 @@ FileSecurityDb::FileSecurityDb(FILE *db_file) fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); /* restore if requested */ - bool restore; - if ((fread(&restore, sizeof(bool), 1, _db_file) == 1) && restore) { - fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET); - fread(&_local_identity, sizeof(_local_identity), 1, _db_file); - - fseek(_db_file, DB_OFFSET_LOCAL_CSRK, SEEK_SET); - fread(&_local_csrk, sizeof(_local_csrk), 1, _db_file); - - fseek(_db_file, DB_OFFSET_LOCAL_SIGN_COUNT, SEEK_SET); - fread(&_local_sign_counter, sizeof(_local_sign_counter), 1, _db_file); - - fseek(_db_file, DB_OFFSET_ENTRIES, SEEK_SET); - /* we read the entries partially and fill the offsets ourselves*/ - for (size_t i = 0; i < get_entry_count(); i++) { - fread(&_entries[i], DB_SIZE_ENTRY, 1, _db_file); + bool restore_toggle; + if (fread(&restore_toggle, sizeof(bool), 1, _db_file) == 1) { + if (restore_toggle) { + restore(); } } @@ -107,49 +96,55 @@ FileSecurityDb::~FileSecurityDb() { } FILE* FileSecurityDb::open_db_file(const char *db_path) { + if (!db_path) { + return NULL; + } + FILE *db_file = fopen(db_path, "wb+"); - if (db_file) { - /* we will check the db file and if the version or size doesn't match - * what we expect we will blank it */ - bool init = false; - uint16_t version; - fseek(db_file, DB_OFFSET_VERSION, SEEK_SET); + if (!db_file) { + return NULL; + } - if ((fread(&version, sizeof(version), 1, db_file) == 1) && - (version == DB_VERSION)) { - /* version checks out, try the size */ - fseek(db_file, DB_SIZE - 1, SEEK_SET); - /* read one byte and expect to hit EOF */ - if ((fread(&version, 1, 1, db_file) != 1) || !feof(db_file)) { - init = true; - } - } else { + /* we will check the db file and if the version or size doesn't match + * what we expect we will blank it */ + bool init = false; + uint16_t version; + + fseek(db_file, DB_OFFSET_VERSION, SEEK_SET); + + if ((fread(&version, sizeof(version), 1, db_file) == 1) && + (version == DB_VERSION)) { + /* version checks out, try the size */ + fseek(db_file, DB_SIZE - 1, SEEK_SET); + /* read one byte and expect to hit EOF */ + if ((fread(&version, 1, 1, db_file) != 1) || !feof(db_file)) { init = true; } + } else { + init = true; + } - if (init) { - fseek(db_file, 0, SEEK_SET); + if (init) { + fseek(db_file, 0, SEEK_SET); - /* zero the file */ - const uint32_t zero = 0; - size_t count = DB_SIZE / 4; - while (count--) { - if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { - fclose(db_file); - return NULL; - } - } - - if (fflush(db_file)) { + /* zero the file */ + const uint32_t zero = 0; + size_t count = DB_SIZE / 4; + while (count--) { + if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { fclose(db_file); return NULL; } } - return db_file; + if (fflush(db_file)) { + fclose(db_file); + return NULL; + } } - return NULL; + + return db_file; } SecurityDistributionFlags_t* FileSecurityDb::get_distribution_flags( @@ -287,6 +282,21 @@ void FileSecurityDb::set_entry_peer_sign_counter( /* saving and loading from nvm */ void FileSecurityDb::restore() { + fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET); + fread(&_local_identity, sizeof(_local_identity), 1, _db_file); + + fseek(_db_file, DB_OFFSET_LOCAL_CSRK, SEEK_SET); + fread(&_local_csrk, sizeof(_local_csrk), 1, _db_file); + + fseek(_db_file, DB_OFFSET_LOCAL_SIGN_COUNT, SEEK_SET); + fread(&_local_sign_counter, sizeof(_local_sign_counter), 1, _db_file); + + fseek(_db_file, DB_OFFSET_ENTRIES, SEEK_SET); + /* we read the entries partially and fill the offsets ourselves*/ + for (size_t i = 0; i < get_entry_count(); i++) { + fread(&_entries[i], DB_SIZE_ENTRY, 1, _db_file); + } + } void FileSecurityDb::sync(entry_handle_t db_handle) { @@ -300,8 +310,12 @@ void FileSecurityDb::sync(entry_handle_t db_handle) { } void FileSecurityDb::set_restore(bool reload) { + fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); + fwrite(&reload, sizeof(bool), 1, _db_file); } +/* helper functions */ + uint8_t FileSecurityDb::get_entry_count() { return MAX_ENTRIES; } From 49db7e2a2a6c97028696ea6eacf54cb37d6307d2 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 15 May 2018 11:46:39 +0100 Subject: [PATCH 14/18] restoring db file blanks file if set to not restore, allow reusing the db --- .../FEATURE_BLE/ble/generic/FileSecurityDb.h | 7 +++ .../source/generic/FileSecurityDb.cpp | 50 +++++++++++-------- .../source/generic/GenericSecurityManager.cpp | 15 +++--- 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index 62cf6fcc48..da95626b28 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -126,6 +126,13 @@ private: virtual SecurityEntryKeys_t* read_in_entry_local_keys(entry_handle_t db_handle); virtual SecurityEntrySigning_t* read_in_entry_peer_signing(entry_handle_t db_handle); + /** + * Zero the db file. + * @param db_file filehandle for file to erase + * @return filehandle when successful, otherwise NULL + */ + static FILE* erase_db_file(FILE* db_file); + private: entry_t _entries[MAX_ENTRIES]; FILE *_db_file; diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 1b8c0357c9..3926496b85 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -75,16 +75,6 @@ typedef SecurityDb::entry_handle_t entry_handle_t; FileSecurityDb::FileSecurityDb(FILE *db_file) : SecurityDb(), _db_file(db_file) { - fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); - - /* restore if requested */ - bool restore_toggle; - if (fread(&restore_toggle, sizeof(bool), 1, _db_file) == 1) { - if (restore_toggle) { - restore(); - } - } - /* init the offset in entries so they point to file positions */ for (size_t i = 0; i < get_entry_count(); i++) { _entries[i].file_offset = DB_OFFSET_STORES + i * DB_SIZE_STORE; @@ -126,24 +116,30 @@ FILE* FileSecurityDb::open_db_file(const char *db_path) { } if (init) { - fseek(db_file, 0, SEEK_SET); + return erase_db_file(db_file); + } - /* zero the file */ - const uint32_t zero = 0; - size_t count = DB_SIZE / 4; - while (count--) { - if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { - fclose(db_file); - return NULL; - } - } + return db_file; +} - if (fflush(db_file)) { +FILE* FileSecurityDb::erase_db_file(FILE* db_file) { + fseek(db_file, 0, SEEK_SET); + + /* zero the file */ + const uint32_t zero = 0; + size_t count = DB_SIZE / 4; + while (count--) { + if (fwrite(&zero, sizeof(zero), 1, db_file) != 1) { fclose(db_file); return NULL; } } + if (fflush(db_file)) { + fclose(db_file); + return NULL; + } + return db_file; } @@ -282,6 +278,18 @@ void FileSecurityDb::set_entry_peer_sign_counter( /* saving and loading from nvm */ void FileSecurityDb::restore() { + + fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); + + /* restore if requested */ + bool restore_toggle; + if (fread(&restore_toggle, sizeof(bool), 1, _db_file) == 1) { + if (!restore_toggle) { + erase_db_file(_db_file); + return; + } + } + fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET); fread(&_local_identity, sizeof(_local_identity), 1, _db_file); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 655bd2f88a..995578bc68 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -42,20 +42,19 @@ ble_error_t GenericSecurityManager::init( bool signing, const char* db_path ) { - if (_db) { - return BLE_ERROR_OPERATION_NOT_PERMITTED; - } ble_error_t err = _pal.initialize(); if (err) { return err; } - FILE* db_file = FileSecurityDb::open_db_file(db_path); - if (db_file) { - _db = new (std::nothrow) FileSecurityDb(db_file); - } else { - _db = new (std::nothrow) MemorySecurityDb(); + if (!_db) { + FILE* db_file = FileSecurityDb::open_db_file(db_path); + if (db_file) { + _db = new (std::nothrow) FileSecurityDb(db_file); + } else { + _db = new (std::nothrow) MemorySecurityDb(); + } } _db->restore(); From 5c598688e4acf84b2e7d15bbaf872b909f71b2f7 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 15 May 2018 16:35:54 +0100 Subject: [PATCH 15/18] templates for reading and writing to avoid repetition --- .../FEATURE_BLE/ble/generic/FileSecurityDb.h | 12 +++ .../source/generic/FileSecurityDb.cpp | 80 ++++++++----------- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index da95626b28..4c57d67005 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -40,6 +40,18 @@ private: return reinterpret_cast(db_handle); } + template + void db_read(T *value, long int offset) { + fseek(_db_file, offset, SEEK_SET); + fread(value, sizeof(T), 1, _db_file); + } + + template + void db_write(T *value, long int offset) { + fseek(_db_file, offset, SEEK_SET); + fwrite(value, sizeof(T), 1, _db_file); + } + public: FileSecurityDb(FILE *db_file); virtual ~FileSecurityDb(); diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 3926496b85..7796a3d715 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -163,8 +163,7 @@ void FileSecurityDb::set_entry_local_ltk( entry->flags.ltk_sent = true; - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK, SEEK_SET); - fwrite(<k, sizeof(ltk_t), 1, _db_file); + db_write(<k, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_LTK); } void FileSecurityDb::set_entry_local_ediv_rand( @@ -177,10 +176,8 @@ void FileSecurityDb::set_entry_local_ediv_rand( return; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV, SEEK_SET); - fwrite(&ediv, sizeof(ediv_t), 1, _db_file); - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND, SEEK_SET); - fwrite(&rand, sizeof(rand_t), 1, _db_file); + db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_EDIV); + db_write(&rand, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS_RAND); } /* peer's keys */ @@ -198,8 +195,7 @@ void FileSecurityDb::set_entry_peer_ltk( entry->flags.ltk_stored = true; - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK, SEEK_SET); - fwrite(<k, sizeof(ltk_t), 1, _db_file); + db_write(<k, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_LTK); } void FileSecurityDb::set_entry_peer_ediv_rand( @@ -212,10 +208,8 @@ void FileSecurityDb::set_entry_peer_ediv_rand( return; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV, SEEK_SET); - fwrite(&ediv, sizeof(ediv_t), 1, _db_file); - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND, SEEK_SET); - fwrite(&rand, sizeof(rand_t), 1, _db_file); + db_write(&ediv, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_EDIV); + db_write(&rand, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS_RAND); } void FileSecurityDb::set_entry_peer_irk( @@ -229,8 +223,7 @@ void FileSecurityDb::set_entry_peer_irk( entry->flags.irk_stored = true; - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK, SEEK_SET); - fwrite(&irk, sizeof(irk_t), 1, _db_file); + db_write(&irk, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_IRK); } void FileSecurityDb::set_entry_peer_bdaddr( @@ -243,10 +236,8 @@ void FileSecurityDb::set_entry_peer_bdaddr( return; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS, SEEK_SET); - fwrite(&peer_address, sizeof(address_t), 1, _db_file); - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC, SEEK_SET); - fwrite(&address_is_public, sizeof(bool), 1, _db_file); + db_write(&peer_address, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS); + db_write(&address_is_public, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY_ADDRESS_IS_PUBLIC); } void FileSecurityDb::set_entry_peer_csrk( @@ -260,9 +251,7 @@ void FileSecurityDb::set_entry_peer_csrk( entry->flags.csrk_stored = true; - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET); - /* only write in the csrk */ - fwrite(&csrk, sizeof(csrk_t), 1, _db_file); + db_write(&csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); } void FileSecurityDb::set_entry_peer_sign_counter( @@ -290,14 +279,9 @@ void FileSecurityDb::restore() { } } - fseek(_db_file, DB_OFFSET_LOCAL_IDENTITY, SEEK_SET); - fread(&_local_identity, sizeof(_local_identity), 1, _db_file); - - fseek(_db_file, DB_OFFSET_LOCAL_CSRK, SEEK_SET); - fread(&_local_csrk, sizeof(_local_csrk), 1, _db_file); - - fseek(_db_file, DB_OFFSET_LOCAL_SIGN_COUNT, SEEK_SET); - fread(&_local_sign_counter, sizeof(_local_sign_counter), 1, _db_file); + db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY); + db_read(&_local_csrk, DB_OFFSET_LOCAL_CSRK); + db_read(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT); fseek(_db_file, DB_OFFSET_ENTRIES, SEEK_SET); /* we read the entries partially and fill the offsets ourselves*/ @@ -313,13 +297,11 @@ void FileSecurityDb::sync(entry_handle_t db_handle) { return; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT, SEEK_SET); - fwrite(&entry->peer_sign_counter, sizeof(sign_count_t), 1, _db_file); + db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); } void FileSecurityDb::set_restore(bool reload) { - fseek(_db_file, DB_OFFSET_RESTORE, SEEK_SET); - fwrite(&reload, sizeof(bool), 1, _db_file); + db_write(&reload, DB_OFFSET_RESTORE); } /* helper functions */ @@ -358,9 +340,11 @@ SecurityEntryIdentity_t* FileSecurityDb::read_in_entry_peer_identity(entry_handl if (!entry) { return NULL; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY, SEEK_SET); - fread(&_buffer, sizeof(SecurityEntryIdentity_t), 1, _db_file); - return reinterpret_cast(_buffer); + + SecurityEntryIdentity_t* identity = reinterpret_cast(_buffer); + db_read(identity, entry->file_offset + DB_STORE_OFFSET_PEER_IDENTITY); + + return identity; }; SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_entry) { @@ -368,9 +352,11 @@ SecurityEntryKeys_t* FileSecurityDb::read_in_entry_peer_keys(entry_handle_t db_e if (!entry) { return NULL; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS, SEEK_SET); - fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file); - return reinterpret_cast(_buffer); + + SecurityEntryKeys_t* keys = reinterpret_cast(_buffer); + db_read(keys, entry->file_offset + DB_STORE_OFFSET_PEER_KEYS); + + return keys; }; SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_entry) { @@ -378,9 +364,11 @@ SecurityEntryKeys_t* FileSecurityDb::read_in_entry_local_keys(entry_handle_t db_ if (!entry) { return NULL; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS, SEEK_SET); - fread(&_buffer, sizeof(SecurityEntryKeys_t), 1, _db_file); - return reinterpret_cast(_buffer); + + SecurityEntryKeys_t* keys = reinterpret_cast(_buffer); + db_read(keys, entry->file_offset + DB_STORE_OFFSET_LOCAL_KEYS); + + return keys; }; SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_t db_entry) { @@ -388,12 +376,14 @@ SecurityEntrySigning_t* FileSecurityDb::read_in_entry_peer_signing(entry_handle_ if (!entry) { return NULL; } - fseek(_db_file, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING, SEEK_SET); /* only read in the csrk */ - fread(&_buffer, sizeof(csrk_t), 1, _db_file); - SecurityEntrySigning_t* signing = reinterpret_cast(_buffer); + csrk_t* csrk = reinterpret_cast(_buffer); + db_read(csrk, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING); + + /* use the counter held in memory */ + SecurityEntrySigning_t* signing = reinterpret_cast(_buffer); signing->counter = entry->peer_sign_counter; return signing; From c2bbc94b4492664b1772a355b85453c2573e9128 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 16 May 2018 11:01:37 +0100 Subject: [PATCH 16/18] handle init of an already initialised security db --- .../source/generic/GenericSecurityManager.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a4e57ec4c9..bb03c2f548 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -48,13 +48,20 @@ ble_error_t GenericSecurityManager::init( return err; } + if (_db) { + delete _db; + } + + FILE* db_file = FileSecurityDb::open_db_file(db_path); + + if (db_file) { + _db = new (std::nothrow) FileSecurityDb(db_file); + } else { + _db = new (std::nothrow) MemorySecurityDb(); + } + if (!_db) { - FILE* db_file = FileSecurityDb::open_db_file(db_path); - if (db_file) { - _db = new (std::nothrow) FileSecurityDb(db_file); - } else { - _db = new (std::nothrow) MemorySecurityDb(); - } + return BLE_ERROR_NO_MEM; } _db->restore(); From bcca75973edd7aa5c1bd4ed90b582140c2f96d56 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 16 May 2018 11:23:17 +0100 Subject: [PATCH 17/18] reseting the security db --- features/FEATURE_BLE/ble/generic/FileSecurityDb.h | 2 ++ features/FEATURE_BLE/ble/generic/MemorySecurityDb.h | 10 ++++++++++ features/FEATURE_BLE/ble/generic/SecurityDb.h | 9 +++++++++ features/FEATURE_BLE/source/generic/FileSecurityDb.cpp | 5 +++++ .../source/generic/GenericSecurityManager.cpp | 2 ++ 5 files changed, 28 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index 4c57d67005..c362f25b26 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -126,6 +126,8 @@ public: virtual void set_restore(bool reload); + virtual void reset(); + private: virtual uint8_t get_entry_count(); diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index 6ca9c3b3b0..a38bb84df9 100644 --- a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -148,6 +148,16 @@ public: } } + + /* saving and loading from nvm */ + + virtual void reset() { + SecurityDb::reset(); + for (size_t i = 0; i < MAX_ENTRIES; ++i) { + _entries[i] = entry_t(); + } + } + private: virtual uint8_t get_entry_count() { return MAX_ENTRIES; diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 009d769554..72a4968fbb 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -656,6 +656,15 @@ public: */ virtual void set_restore(bool reload) { }; + /** + * Reset the databse by removing all information + */ + virtual void reset() { + _local_identity = SecurityEntryIdentity_t(); + _local_csrk = csrk_t(); + _local_sign_counter = 0; + } + private: /** * Get an entry for a new connection not present in the db yet. This will find a free entry diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 7796a3d715..4a300c6a5b 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -304,6 +304,11 @@ void FileSecurityDb::set_restore(bool reload) { db_write(&reload, DB_OFFSET_RESTORE); } +void FileSecurityDb::reset() { + SecurityDb::reset(); + erase_db_file(_db_file); +} + /* helper functions */ uint8_t FileSecurityDb::get_entry_count() { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index bb03c2f548..3f8873d112 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -116,7 +116,9 @@ ble_error_t GenericSecurityManager::init( } ble_error_t GenericSecurityManager::reset(void) { + MBED_ASSERT(_db); _pal.reset(); + _db->reset(); SecurityManager::reset(); return BLE_ERROR_NONE; From 1ae13bc80f59c0d7ad90fafba6d4262a58a2d081 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 16 May 2018 11:46:36 +0100 Subject: [PATCH 18/18] don't reset db on security manager reset as the docs require --- features/FEATURE_BLE/ble/generic/FileSecurityDb.h | 2 -- features/FEATURE_BLE/ble/generic/MemorySecurityDb.h | 10 ---------- features/FEATURE_BLE/ble/generic/SecurityDb.h | 9 --------- features/FEATURE_BLE/source/generic/FileSecurityDb.cpp | 5 ----- .../source/generic/GenericSecurityManager.cpp | 2 -- 5 files changed, 28 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h index c362f25b26..4c57d67005 100644 --- a/features/FEATURE_BLE/ble/generic/FileSecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/FileSecurityDb.h @@ -126,8 +126,6 @@ public: virtual void set_restore(bool reload); - virtual void reset(); - private: virtual uint8_t get_entry_count(); diff --git a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h index a38bb84df9..6ca9c3b3b0 100644 --- a/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/MemorySecurityDb.h @@ -148,16 +148,6 @@ public: } } - - /* saving and loading from nvm */ - - virtual void reset() { - SecurityDb::reset(); - for (size_t i = 0; i < MAX_ENTRIES; ++i) { - _entries[i] = entry_t(); - } - } - private: virtual uint8_t get_entry_count() { return MAX_ENTRIES; diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 72a4968fbb..009d769554 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -656,15 +656,6 @@ public: */ virtual void set_restore(bool reload) { }; - /** - * Reset the databse by removing all information - */ - virtual void reset() { - _local_identity = SecurityEntryIdentity_t(); - _local_csrk = csrk_t(); - _local_sign_counter = 0; - } - private: /** * Get an entry for a new connection not present in the db yet. This will find a free entry diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 4a300c6a5b..7796a3d715 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -304,11 +304,6 @@ void FileSecurityDb::set_restore(bool reload) { db_write(&reload, DB_OFFSET_RESTORE); } -void FileSecurityDb::reset() { - SecurityDb::reset(); - erase_db_file(_db_file); -} - /* helper functions */ uint8_t FileSecurityDb::get_entry_count() { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 3f8873d112..bb03c2f548 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -116,9 +116,7 @@ ble_error_t GenericSecurityManager::init( } ble_error_t GenericSecurityManager::reset(void) { - MBED_ASSERT(_db); _pal.reset(); - _db->reset(); SecurityManager::reset(); return BLE_ERROR_NONE;