From 7b6b02a7468b8e995db5c3275642067bb622b75f Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Thu, 1 Mar 2018 19:50:13 +0000 Subject: [PATCH 001/274] Nordic PAL - Breaks existing SM --- .../TARGET_NRF5/source/btle/btle.cpp | 10 +- .../source/btle/btle_security_pm.cpp | 6 +- .../TARGET_NRF5/source/nRF5xGap.cpp | 75 +++- .../TARGET_NRF5/source/nRF5xGap.h | 47 ++- .../source/nRF5xPalSecurityManager.cpp | 366 +++++++++++------- .../source/nRF5xPalSecurityManager.h | 145 +++---- .../TARGET_NRF5/source/nRF5xn.cpp | 30 +- .../TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h | 46 +-- 8 files changed, 455 insertions(+), 270 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp index 0873336a44..1da18dd40e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp @@ -53,7 +53,7 @@ extern "C" { #include "nrf_ble_hci.h" #include "nRF5XPalGattClient.h" - +#include "nRF5XPalSecurityManager.h" bool isEventsSignaled = false; @@ -171,6 +171,7 @@ error_t btle_init(void) static void btle_handler(ble_evt_t *p_ble_evt) { using ble::pal::vendor::nordic::nRF5XGattClient; + using ble::pal::vendor::nordic::nRF5xSecurityManager; /* Library service handlers */ #if SDK_CONN_PARAMS_MODULE_ENABLE @@ -265,10 +266,6 @@ static void btle_handler(ble_evt_t *p_ble_evt) break; } - case BLE_GAP_EVT_PASSKEY_DISPLAY: - securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); - break; - case BLE_GAP_EVT_TIMEOUT: gap.processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); break; @@ -296,6 +293,9 @@ static void btle_handler(ble_evt_t *p_ble_evt) break; } + // Process security manager events + securityManager.sm_handler(p_ble_evt); + gattServer.hwCallback(p_ble_evt); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp index 6042b71753..09afdebe5c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp @@ -26,6 +26,7 @@ extern "C" { } #include "btle_security.h" +#if 0 static bool initialized = false; @@ -389,6 +390,7 @@ void pm_handler(pm_evt_t const *p_event) } } +#endif #if (NRF_SD_BLE_API_VERSION <= 2) ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) @@ -406,7 +408,6 @@ btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) } } #endif - bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) { @@ -416,7 +417,7 @@ btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_i */ return im_address_resolve(p_addr, p_irk); } - +#if 0 void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) { @@ -484,3 +485,4 @@ ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) #endif #endif // defined(S130) || defined(S132) || defined(S140) +#endif \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index 56c9218fee..33bb4dda98 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -37,6 +37,15 @@ void radioNotificationStaticCallback(bool param) { gap.processRadioNotificationEvent(param); } +nRF5xGap::nRF5xGap() : Gap(), + advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), + scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), + whitelistAddressesSize(0), + _connection_event_handler(NULL) +{ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; +} + /**************************************************************************/ /*! @brief Sets the advertising parameters and payload for the device @@ -936,26 +945,18 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const /*! @brief Helper function used to populate the ble_gap_whitelist_t that will be used by the SoftDevice for filtering requests. - @returns \ref ble_error_t - @retval BLE_ERROR_NONE Everything executed properly - @retval BLE_ERROR_INVALID_STATE The internal stack was not initialized correctly. - @note Both the SecurityManager and Gap must initialize correctly for this function to succeed. - @note This function is needed because for the BLE API the whitelist is just a collection of keys, but for the stack it also includes the IRK table. - @section EXAMPLE - @code - @endcode */ /**************************************************************************/ @@ -1048,6 +1049,8 @@ ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) { + using ble::pal::vendor::nordic::nRF5xSecurityManager; + pm_peer_id_t peer_id; ret_code_t ret; @@ -1095,7 +1098,7 @@ ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAd { //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info)) + if (btle_matchAddressAndIrk(address, irk)) { // Copy data to the buffer. memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); @@ -1195,3 +1198,57 @@ ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() return applyWhiteIdentityList(whiteAndIdentityList); } #endif + +void nRF5xGap::set_connection_event_handler(ble::pal::ConnectionEventHandler *connection_event_handler) +{ + _connection_event_handler = connection_event_handler; +} + +void nRF5xGap::processConnectionEvent( + Handle_t handle, + Role_t role, + BLEProtocol::AddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams +) { + if (_connection_event_handler) { + _connection_event_handler->on_connected( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams + ); + } + + ::Gap::processConnectionEvent( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams + ); +} + +void nRF5xGap::processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason +) { + if (_connection_event_handler) { + _connection_event_handler->on_disconnected( + handle, + reason + ); + } + + ::Gap::processDisconnectionEvent( + handle, + reason + ); +} \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h index 922260954a..2e454403ef 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h @@ -44,6 +44,7 @@ #include "ble/GapAdvertisingData.h" #include "ble/Gap.h" #include "ble/GapScanningParams.h" +#include "ble/pal/ConnectionEventMonitor.h" #include "nrf_soc.h" @@ -52,19 +53,20 @@ extern "C" { #include "app_util_platform.h" } -#include "btle_security.h" - void radioNotificationStaticCallback(bool param); +namespace ble { namespace pal { class ConnectionEventHandler; }} + /**************************************************************************/ /*! \brief */ /**************************************************************************/ -class nRF5xGap : public Gap -{ +class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor { public: + nRF5xGap(); + /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); @@ -254,21 +256,42 @@ private: } friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */ -private: +public: + /** @note Implements ConnectionEventMonitor. + * @copydoc ConnectionEventMonitor::set_connection_event_handler + */ + void set_connection_event_handler(ble::pal::ConnectionEventHandler *_connection_event_handler); + + /** + * @copydoc ::Gap::processConnectionEvent + */ + void processConnectionEvent( + Handle_t handle, + Role_t role, + BLEProtocol::AddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams + ); + + /** + * @copydoc ::Gap::processDisconnectionEvent + */ + void processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason + ); + uint16_t m_connectionHandle; + ble::pal::ConnectionEventHandler* _connection_event_handler; + /* * Allow instantiation from nRF5xn when required. */ friend class nRF5xn; - nRF5xGap() : - advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), - scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), - whitelistAddressesSize(0) { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; - } - nRF5xGap(nRF5xGap const &); void operator=(nRF5xGap const &); }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index bdc5b9a6b9..0111ea1eb8 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -17,6 +17,7 @@ #include "nRF5xPalSecurityManager.h" #include "nrf_ble.h" #include "nrf_ble_gap.h" +#include "nrf_soc.h" namespace ble { namespace pal { @@ -33,7 +34,12 @@ static ble_error_t convert_sd_error(uint32_t err) { nRF5xSecurityManager::nRF5xSecurityManager() : ::ble::pal::SecurityManager(), + _use_legacy_pairing(true), + _use_secure_connections(true), + _use_default_passkey(false), + _default_passkey(0), _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), + _min_encryption_key_size(7), _max_encryption_key_size(16) { @@ -50,17 +56,17 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { - return BLE_ERROR_NOT_IMPLEMENTED; + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::terminate() { - return BLE_ERROR_NOT_IMPLEMENTED; + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::reset() { - return BLE_ERROR_NOT_IMPLEMENTED; + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// @@ -100,16 +106,19 @@ ble_error_t nRF5xSecurityManager::clear_resolving_list() // Feature support // +ble_error_t nRF5xSecurityManager::set_secure_connections_support( + bool enabled, bool secure_connections_only +) { + _use_secure_connections = enabled; + _use_legacy_pairing = !enabled || (enabled && !secure_connections_only); + return BLE_ERROR_NONE; +} + ble_error_t nRF5xSecurityManager::get_secure_connections_support( bool &enabled ) { - return BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xSecurityManager::set_io_capability( - io_capability_t io_capability -) { - _io_capability = io_capability; + // NRF5x platforms support secure connections + _use_secure_connections = true; return BLE_ERROR_NONE; } @@ -131,69 +140,61 @@ ble_error_t nRF5xSecurityManager::get_authentication_timeout( return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size -) { - _max_encryption_key_size = max_encryption_key_size; - return BLE_ERROR_NONE; -} - ble_error_t nRF5xSecurityManager::slave_security_request( connection_handle_t connection, AuthenticationMask authentication ) { - return BLE_ERROR_NOT_IMPLEMENTED; + // In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. + + ble_gap_sec_params_t security_params = { + /* bond */ authentication.get_bondable(), + /* mitm */ authentication.get_mitm(), + /* lesc */ authentication.get_secure_connections(), + /* keypress */ authentication.get_keypress_notification(), + 0 + }; + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + return convert_sd_error(err); } //////////////////////////////////////////////////////////////////////////// // Encryption // -ble_error_t nRF5xSecurityManager::enable_encryption( - connection_handle_t connection, - const ltk_t <k -) { - // use sd_ble_gap_encrypt it requires: - // - ediv - // - rand - // - ltk - // - flag indicating if the key was generated with lesc - // - flag indicated if the key is an authenticated key - // - flag indicating the length of the ltk ??? - return BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xSecurityManager::disable_encryption(connection_handle_t connection) -{ - // NO FUNCTION to disable encryption - return BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xSecurityManager::get_encryption_status( - connection_handle_t connection, LinkSecurityStatus_t &status -) { - return BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xSecurityManager::get_encryption_key_size( - connection_handle_t connection, uint8_t &bitsize -) { - return BLE_ERROR_NOT_IMPLEMENTED; -} - ble_error_t nRF5xSecurityManager::enable_encryption( connection_handle_t connection, const ltk_t <k, const rand_t &rand, - const ediv_t &ediv + const ediv_t &ediv, + bool mitm ) { - // NO FUNCTION to disable encryption - return BLE_ERROR_NOT_IMPLEMENTED; + ble_gap_master_id_t master_id; + ble_gap_enc_info_t enc_info; + + memcpy(master_id.rand, rand.data(), rand.size()); + memcpy(&master_id.ediv, ediv.data(), ediv.size()); + + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = _use_secure_connections; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::encrypt_data( - const key_t &key, + const byte_array_t<16> &key, encryption_block_t &data ) { // NO FUNCTION to disable encryption @@ -214,29 +215,93 @@ ble_error_t nRF5xSecurityManager::set_private_address_timeout( // Keys // +ble_error_t nRF5xSecurityManager::set_ltk( + connection_handle_t connection, + const ltk_t& ltk, + bool mitm, + bool secure_connections +) { + ble_gap_enc_info_t enc_info; + + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = secure_connections; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + &enc_info, + NULL, + NULL // Not supported + ); + + return convert_sd_error(err); +} + ble_error_t nRF5xSecurityManager::set_ltk_not_found( connection_handle_t connection ) { - // usefulness ? - return BLE_ERROR_NOT_IMPLEMENTED; -} + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + NULL, + NULL, + NULL // Not supported + ); -ble_error_t nRF5xSecurityManager::set_ltk( - connection_handle_t connection, const ltk_t <k -) { - // usefulness ? - return BLE_ERROR_NOT_IMPLEMENTED; + return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) { - memcpy(_irk.buffer(), irk.data(), _csrk.size()); - return BLE_ERROR_NONE; + // TODO + return BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xSecurityManager::set_csrk(const csrk_t& csrk) { - memcpy(_csrk.buffer(), csrk.data(), _csrk.size()); + // TODO + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t nRF5xSecurityManager::generate_public_key() +{ + // FIXME + return BLE_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////////// +// Global parameters +// + +ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) +{ + if (passkey) { + _use_default_passkey = true; + _default_passkey = passkey; + } else { + _use_default_passkey = false; + } + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) +{ + _io_capability = io_capability; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size +) { + if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || + (min_encryption_key_size > max_encryption_key_size)) { + return BLE_ERROR_INVALID_PARAM; + } + + _min_encryption_key_size = min_encryption_key_size; + _max_encryption_key_size = max_encryption_key_size; + return BLE_ERROR_NONE; } @@ -250,7 +315,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_request( AuthenticationMask authentication_requirements, KeyDistribution initiator_dist, KeyDistribution responder_dist -) { +) { ble_gap_sec_params_t security_params = { /* bond */ authentication_requirements.get_bondable(), /* mitm */ authentication_requirements.get_mitm(), @@ -258,7 +323,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_request( /* keypress */ authentication_requirements.get_keypress_notification(), /* io_caps */ _io_capability.value(), /* oob */ oob_data_flag, - /* min_key_size */ 7, // FIXME! + /* min_key_size */ _min_encryption_key_size, /* max_key_size */ _max_encryption_key_size, /* kdist_periph */ { /* enc */ responder_dist.get_encryption(), @@ -296,7 +361,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_response( /* keypress */ authentication_requirements.get_keypress_notification(), /* io_caps */ _io_capability.value(), /* oob */ oob_data_flag, - /* min_key_size */ 7, // FIXME! + /* min_key_size */ _min_encryption_key_size, /* max_key_size */ _max_encryption_key_size, /* kdist_periph */ { /* enc */ responder_dist.get_encryption(), @@ -314,13 +379,16 @@ ble_error_t nRF5xSecurityManager::send_pairing_response( ble_gap_sec_keyset_t keyset = { /* keys_own */ { - /* encryption key */ NULL, - /* id key */ NULL, /* FIXME: pass in the IRK mixed up with address ?!?*/ - /* signing key */ NULL, /* FIXME: put _csrk in the type of data structure used by nordic */ - /* P-256 Public Key */ NULL + /* encryption key */ &_sp_own_enc_key, + /* id key */ &_sp_own_id_key, + /* signing key */ &_sp_own_sign_key, + /* P-256 Public Key */ &_sp_own_pk }, /* keys_peer */ { - // FIXME: The softdevice requires the application to maintain this memory chunk ... + /* encryption key */ &_sp_peer_enc_key, + /* id key */ &_sp_peer_id_key, + /* signing key */ &_sp_peer_sign_key, + /* P-256 Public Key */ &_sp_peer_pk } }; @@ -344,71 +412,35 @@ ble_error_t nRF5xSecurityManager::cancel_pairing( // sd_ble_gap_auth_key_reply should be used to cancel pairing when a key // entered by the user is required. - uint32_t err = sd_ble_gap_sec_params_reply( - connection, - /* status */ reason.value() | 0x80, - /* params */ NULL, - /* keys ... */ NULL - ); - - return convert_sd_error(err); -} - -ble_error_t nRF5xSecurityManager::request_authentication(connection_handle_t connection) -{ - uint8_t authentication_requirements; - // FIXME: need authentication requirements from the caller - ble_gap_sec_params_t security_params = { - /* bond */ static_cast((authentication_requirements >> 0) & 3), - /* mitm */static_cast((authentication_requirements >> 2) & 1), - /* lesc */ static_cast((authentication_requirements >> 3) & 1), - /* keypress */ static_cast((authentication_requirements >> 4) & 1) - /* other parameters ignored ??? TODO: check*/ - }; - - uint32_t err = sd_ble_gap_authenticate( - connection, - &security_params - ); - - return convert_sd_error(err); + return BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) { - return BLE_ERROR_NOT_IMPLEMENTED; + uint32_t err = sd_rand_application_vector_get(random_data.buffer(), random_data.size()); + return convert_sd_error(err); } -ble_error_t nRF5xSecurityManager::generate_public_key() -{ - return BLE_ERROR_NOT_IMPLEMENTED; -} - - //////////////////////////////////////////////////////////////////////////// // MITM // -ble_error_t nRF5xSecurityManager::set_display_passkey( - passkey_num_t passkey -) { - return BLE_ERROR_NOT_IMPLEMENTED; -} - ble_error_t nRF5xSecurityManager::passkey_request_reply( connection_handle_t connection, const passkey_num_t passkey ) { + PasskeyAscii pkasc(passkey); uint32_t err = sd_ble_gap_auth_key_reply( connection, BLE_GAP_AUTH_KEY_TYPE_PASSKEY, - /* FIXME: convert passkey_num into and asci key */ NULL + pkasc.value() ); return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::legacy_pairing_oob_data_request_reply( - connection_handle_t connection, const oob_tk_t& oob_data + connection_handle_t connection, + const oob_tk_t& oob_data ) { uint32_t err = sd_ble_gap_auth_key_reply( connection, @@ -422,13 +454,39 @@ ble_error_t nRF5xSecurityManager::legacy_pairing_oob_data_request_reply( ble_error_t nRF5xSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { - return BLE_ERROR_NOT_IMPLEMENTED; + uint32_t err; + + if(confirmation) { + // Accept + err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, + NULL + ); + } + else { + // Reject + err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_NONE, + NULL + ); + } + + return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::send_keypress_notification( connection_handle_t connection, Keypress_t keypress ) { - return BLE_ERROR_NOT_IMPLEMENTED; + uint8_t kp_not = static_cast(keypress); + + uint32_t err = sd_ble_gap_keypress_notify( + connection, + kp_not + ); + + return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::oob_data_verified( @@ -447,8 +505,9 @@ nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) { - SecurityManagerEventHandler* handler = + SecurityManager::EventHandler* handler = get_security_manager().get_event_handler(); + nRF5xSecurityManager* inst = &nRF5xSecurityManager::get_security_manager(); if ((evt == NULL) || (handler == NULL)) { return false; @@ -514,7 +573,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) if (req.match_request == 0) { handler->on_passkey_display( connection, - 0 /* TODO: conversion of req.passkey into a numerical passkey */ + PasskeyAscii::to_num(req.passkey) ); } else { // handle this case for secure pairing @@ -523,15 +582,19 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) return true; } - case BLE_GAP_EVT_KEY_PRESSED: - // TODO: add with LESC support + case BLE_GAP_EVT_KEY_PRESSED: { + const ble_gap_evt_key_pressed_t& notf = gap_evt.params.key_pressed; + handler->on_keypress_notification( + connection, + (Keypress_t)notf.kp_not + ); return true; - + } case BLE_GAP_EVT_AUTH_KEY_REQUEST: { uint8_t key_type = gap_evt.params.auth_key_request.key_type; switch (key_type) { - case BLE_GAP_AUTH_KEY_TYPE_NONE: + case BLE_GAP_AUTH_KEY_TYPE_NONE: // Illegal break; case BLE_GAP_AUTH_KEY_TYPE_PASSKEY: @@ -556,10 +619,34 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) switch (status.auth_status) { case BLE_GAP_SEC_STATUS_SUCCESS: - // FIXME: needs success handler + // Keys stored (_sp*) are valid + handler->on_keys_distributed_local_ltk( + connection, + ltk_t(inst->_sp_own_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_local_ediv_rand( + connection, + ediv_t(reinterpret_cast(&inst->_sp_own_enc_key.master_id.ediv)), + inst->_sp_own_enc_key.master_id.rand + ); + + handler->on_keys_distributed_ltk( + connection, + ltk_t(inst->_sp_peer_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_ediv_rand( + connection, + ediv_t(reinterpret_cast(&inst->_sp_peer_enc_key.master_id.ediv)), + inst->_sp_peer_enc_key.master_id.rand + ); break; + + // TODO add signing & privacy keys here + case BLE_GAP_SEC_STATUS_TIMEOUT: - // FIXME: needs timeout handler + handler->on_pairing_timed_out(connection); break; case BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED: @@ -591,17 +678,34 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) } case BLE_GAP_EVT_CONN_SEC_UPDATE: - // FIXME: Invoke handler indicating the link encryption + { + const ble_gap_evt_conn_sec_update_t& req = + gap_evt.params.conn_sec_update; + if( (req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2) ) + { + handler->on_link_encryption_result(connection, link_encryption_t::ENCRYPTED); + } + else + { + handler->on_link_encryption_result(connection, link_encryption_t::NOT_ENCRYPTED); + } return true; - + } case BLE_GAP_EVT_TIMEOUT: // FIXME: forward event when available return true; case BLE_GAP_EVT_SEC_REQUEST: - // FIXME: forward event when available + { + const ble_gap_evt_sec_request_t& req = + gap_evt.params.sec_request; + AuthenticationMask auth_mask(req.bond, req.mitm, req.lesc, req.keypress); + handler->on_slave_security_request( + connection, + auth_mask + ); return true; - + } default: return false; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 3e6b325046..8ae980d488 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -17,6 +17,7 @@ #ifndef NRF5X_PAL_SECURITY_MANAGER_ #define NRF5X_PAL_SECURITY_MANAGER_ +#include "ble/BLETypes.h" #include "ble/pal/PalSecurityManager.h" #include "nrf_ble.h" @@ -85,6 +86,13 @@ public: // Feature support // + /** + * @see ::ble::pal::SecurityManager::set_secure_connections_support + */ + virtual ble_error_t set_secure_connections_support( + bool enabled, bool secure_connections_only = false + ); + /** * @see ::ble::pal::SecurityManager::get_secure_connections_support */ @@ -92,13 +100,6 @@ public: bool &enabled ); - /** - * @see ::ble::pal::SecurityManager::set_io_capability - */ - virtual ble_error_t set_io_capability( - io_capability_t io_capability - ); - //////////////////////////////////////////////////////////////////////////// // Security settings // @@ -117,17 +118,6 @@ public: connection_handle_t, uint16_t &timeout_in_10ms ); - /** - * @see ::ble::pal::SecurityManager::set_encryption_key_requirements - */ - virtual ble_error_t set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size - ); - - /** - * @see ::ble::pal::SecurityManager::slave_security_request - */ virtual ble_error_t slave_security_request( connection_handle_t connection, AuthenticationMask authentication @@ -142,26 +132,10 @@ public: */ virtual ble_error_t enable_encryption( connection_handle_t connection, - const ltk_t <k - ); - - /** - * @see ::ble::pal::SecurityManager::disable_encryption - */ - virtual ble_error_t disable_encryption(connection_handle_t connection); - - /** - * @see ::ble::pal::SecurityManager::get_encryption_status - */ - virtual ble_error_t get_encryption_status( - connection_handle_t connection, LinkSecurityStatus_t &status - ); - - /** - * @see ::ble::pal::SecurityManager::get_encryption_key_size - */ - virtual ble_error_t get_encryption_key_size( - connection_handle_t, uint8_t &bitsize + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm ); /** @@ -170,8 +144,7 @@ public: virtual ble_error_t enable_encryption( connection_handle_t connection, const ltk_t <k, - const rand_t &rand, - const ediv_t &ediv + bool mitm ); /** @@ -198,22 +171,56 @@ public: /** * @see ::ble::pal::SecurityManager::set_ltk */ - virtual ble_error_t set_ltk(connection_handle_t connection, const ltk_t <k); + virtual ble_error_t set_ltk( + connection_handle_t connection, + const ltk_t <k, + bool mitm, + bool secure_connections + ); /** - * @see ::ble::pal::SecurityManager::set_ltk + * @see ::ble::pal::SecurityManager::set_ltk_not_found */ - virtual ble_error_t set_ltk_not_found(connection_handle_t connection); + virtual ble_error_t set_ltk_not_found( + connection_handle_t connection + ); /** * @see ::ble::pal::SecurityManager::set_irk */ - virtual ble_error_t set_irk(const irk_t& irk); + virtual ble_error_t set_irk(const irk_t &irk); /** * @see ::ble::pal::SecurityManager::set_csrk */ - virtual ble_error_t set_csrk(const csrk_t& csrk); + virtual ble_error_t set_csrk(const csrk_t &csrk); + + /** + * @see ::ble::pal::SecurityManager::generate_public_key + */ + virtual ble_error_t generate_public_key(); + + //////////////////////////////////////////////////////////////////////////// + // Global parameters + // + + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); //////////////////////////////////////////////////////////////////////////// // Authentication @@ -248,44 +255,29 @@ public: connection_handle_t connection, pairing_failure_t reason ); - /** - * @see ::ble::pal::SecurityManager::request_authentication - */ - virtual ble_error_t request_authentication(connection_handle_t connection); - /** * @see ::ble::pal::SecurityManager::get_random_data */ virtual ble_error_t get_random_data(byte_array_t<8> &random_data); - /** - * @see ::ble::pal::SecurityManager::generate_public_key - */ - virtual ble_error_t generate_public_key(); - //////////////////////////////////////////////////////////////////////////// // MITM // /** - * @see ::ble::pal::SecurityManager::set_display_passkey + * @see ::ble::pal::SecurityManager::passkey_request_reply */ - virtual ble_error_t set_display_passkey( + virtual ble_error_t passkey_request_reply( + connection_handle_t connection, passkey_num_t passkey ); /** - * @see ::ble::pal::SecurityManager::passkey_request_reply - */ - virtual ble_error_t passkey_request_reply( - connection_handle_t connection, const passkey_num_t passkey - ); - - /** - * @see ::ble::pal::SecurityManager::oob_data_request_reply + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply */ virtual ble_error_t legacy_pairing_oob_data_request_reply( - connection_handle_t connection, const oob_tk_t& oob_data + connection_handle_t connection, + const oob_tk_t &oob_data ); /** @@ -315,14 +307,31 @@ public: static nRF5xSecurityManager& get_security_manager(); // Event handler - // FIXME: set proper event handling type - static bool sm_handler(const ble_evt_t *evt); + bool sm_handler(const ble_evt_t *evt); private: + bool _use_legacy_pairing; + bool _use_secure_connections; + bool _use_default_passkey; + passkey_num_t _default_passkey; + irk_t _irk; csrk_t _csrk; + io_capability_t _io_capability; + uint8_t _min_encryption_key_size; uint8_t _max_encryption_key_size; + + // The softdevice requires us to manage memory for these keys + ble_gap_enc_key_t _sp_own_enc_key; + ble_gap_id_key_t _sp_own_id_key; + ble_gap_sign_info_t _sp_own_sign_key; + ble_gap_lesc_p256_pk_t _sp_own_pk; + + ble_gap_enc_key_t _sp_peer_enc_key; + ble_gap_id_key_t _sp_peer_id_key; + ble_gap_sign_info_t _sp_peer_sign_key; + ble_gap_lesc_p256_pk_t _sp_peer_pk; }; } // nordic 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 111bfc1bb0..75d0e48047 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 @@ -62,8 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())), - securityManagerInstance(NULL) + gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())) { } @@ -171,7 +170,6 @@ ble_error_t nRF5xn::shutdown(void) return BLE_STACK_BUSY; } - /* Shutdown the BLE API and nRF51 glue code */ ble_error_t error; @@ -182,13 +180,6 @@ ble_error_t nRF5xn::shutdown(void) } } - if (securityManagerInstance != NULL) { - error = securityManagerInstance->reset(); - if (error != BLE_ERROR_NONE) { - return error; - } - } - /* S110 does not support BLE client features, nothing to reset. */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) error = getGattClient().reset(); @@ -209,6 +200,25 @@ ble_error_t nRF5xn::shutdown(void) return BLE_ERROR_NONE; } +SecurityManager& nRF5xn::getSecurityManager() +{ + const nRF5xn* self = this; + return const_cast(self->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 ble::generic::GenericSecurityManager m_instance( + m_pal, + m_db, + const_cast(getGap()) + ); + + return m_instance; +} + void nRF5xn::waitForEvent(void) { 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 154b9e49dc..99954738cb 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 @@ -21,10 +21,14 @@ #include "ble/blecommon.h" #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" + #include "nRF5xGap.h" #include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" #include "btle.h" @@ -82,18 +86,14 @@ public: } /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A reference to GattServer. + * @see BLEInstanceBase::getSecurityManager */ - virtual nRF5xSecurityManager &getSecurityManager() { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; /** * Accessors to GAP. This function checks whether gapInstance points to an @@ -130,23 +130,6 @@ public: return *gattServerInstance; }; - /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A const reference to GattServer. - * - * @note The accessor is able to modify the object's state because the - * internal pointer has been declared mutable. - */ - virtual const nRF5xSecurityManager &getSecurityManager() const { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } - virtual void waitForEvent(void); virtual void processEvents(); @@ -170,10 +153,7 @@ private: * it can be assigned inside a 'const' function. */ ble::generic::GenericGattClient gattClient; - mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance. - * If NULL, then SecurityManager has not been initialized. - * The pointer has been declared as 'mutable' so that - * it can be assigned inside a 'const' function. */ + }; #endif From 713ab14d22337136989edea7c16ed0be74724d30 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Thu, 1 Mar 2018 20:06:38 +0000 Subject: [PATCH 002/274] Removed deprecated Security Manager --- .../TARGET_NRF5/source/btle/btle.cpp | 13 +- .../TARGET_NRF5/source/btle/btle_security.cpp | 326 ------------ .../TARGET_NRF5/source/btle/btle_security.h | 146 ------ .../source/btle/btle_security_pm.cpp | 488 ------------------ .../TARGET_NRF5/source/nRF5xGap.cpp | 158 +----- .../source/nRF5xPalSecurityManager.cpp | 38 +- .../source/nRF5xPalSecurityManager.h | 2 +- .../TARGET_NRF5/source/nRF5xSecurityManager.h | 194 ------- 8 files changed, 35 insertions(+), 1330 deletions(-) delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.cpp delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.h delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xSecurityManager.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp index 1da18dd40e..d3b63c211b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp @@ -38,11 +38,9 @@ extern "C" { #if (IS_LEGACY_DEVICE_MANAGER_ENABLED) #include "pstorage.h" - #include "device_manager.h" #else #include "fstorage.h" #include "fds.h" - #include "peer_manager.h" #include "ble_conn_state.h" #endif @@ -145,9 +143,6 @@ error_t btle_init(void) return ERROR_INVALID_PARAM; } - // Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp) - pm_init(); - #if (NRF_SD_BLE_API_VERSION <= 2) ble_gap_addr_t addr; if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) { @@ -157,9 +152,7 @@ error_t btle_init(void) return ERROR_INVALID_PARAM; } #else - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - pm_privacy_set(&privacy_params); + #endif ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler)); @@ -179,14 +172,10 @@ static void btle_handler(ble_evt_t *p_ble_evt) #endif #if (IS_LEGACY_DEVICE_MANAGER_ENABLED) - dm_ble_evt_handler(p_ble_evt); #else // Forward BLE events to the Connection State module. // This must be called before any event handler that uses this module. ble_conn_state_on_ble_evt(p_ble_evt); - - // Forward BLE events to the Peer Manager - pm_on_ble_evt(p_ble_evt); #endif #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.cpp deleted file mode 100644 index 389c9b5c4c..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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. - */ -#if defined(S110) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "pstorage.h" -#include "device_manager.h" -#include "id_manager.h" -} - -#include "btle_security.h" - -static dm_application_instance_t applicationInstance; -static bool initialized = false; -static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result); - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 1, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - if (pstorage_init() != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - dm_init_param_t dm_init_param = { - .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */ - }; - if (dm_init(&dm_init_param) != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - const dm_application_param_t dm_param = { - .evt_handler = dm_handler, - .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID, - .sec_param = securityParameters - }; - - if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - dm_handle_t dmHandle = { - .appl_id = applicationInstance, - }; - if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) { - if (rc == NRF_ERROR_NOT_FOUND) { - return BLE_ERROR_INVALID_PARAM; - } else { - return BLE_ERROR_UNSPECIFIED; - } - } - - if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast(securityStatusP))) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ble_gap_sec_params_t params = securityParameters; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - uint32_t result = sd_ble_gap_authenticate(connectionHandle, ¶ms); - - if (result == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_UNSPECIFIED; - } -} - -ret_code_t -dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - - switch (p_event->event_id) { - case DM_EVT_SECURITY_SETUP: /* started */ { - const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - break; - } - case DM_EVT_SECURITY_SETUP_COMPLETE: - securityManager. - processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, - (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); - break; - case DM_EVT_LINK_SECURED: { - unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm; - unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv; - SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - switch (securityMode) { - case 1: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); - break; - } - case DM_EVT_DEVICE_CONTEXT_STORED: - securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); - break; - default: - break; - } - - return NRF_SUCCESS; -} - -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} - - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} -#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.h deleted file mode 100644 index a1354a36ee..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security.h +++ /dev/null @@ -1,146 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 _BTLE_SECURITY_H_ -#define _BTLE_SECURITY_H_ - -#include "ble/Gap.h" -#include "ble/SecurityManager.h" - -/** - * Function to test whether the SecurityManager has been initialized. - * Possible by a call to @ref btle_initializeSecurity(). - * - * @return True if the SecurityManager was previously initialized, false - * otherwise. - */ -bool btle_hasInitializedSecurity(void); - -/** - * Enable Nordic's Device Manager, which brings in functionality from the - * stack's Security Manager. The Security Manager implements the actual - * cryptographic algorithms and protocol exchanges that allow two devices to - * securely exchange data and privately detect each other. - * - * @param[in] enableBonding Allow for bonding. - * @param[in] requireMITM Require protection for man-in-the-middle attacks. - * @param[in] iocaps To specify IO capabilities of this peripheral, - * such as availability of a display or keyboard to - * support out-of-band exchanges of security data. - * @param[in] passkey To specify a static passkey. - * - * @return BLE_ERROR_NONE on success. - */ -ble_error_t btle_initializeSecurity(bool enableBonding = true, - bool requireMITM = true, - SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE, - const SecurityManager::Passkey_t passkey = NULL); - -/** - * Get the security status of a link. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[out] securityStatusP - * security status. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP); - -/** - * Set the security mode on a connection. Useful for elevating the security mode - * once certain conditions are met, e.g., a particular service is found. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[in] securityMode - * security mode. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode); - -/** - * Function for deleting all peer device context and all related bonding - * information from the database. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. - * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or - * application registration. - */ -ble_error_t btle_purgeAllBondingState(void); - -#if (NRF_SD_BLE_API_VERSION <= 2) -/** - * Query the SoftDevice bond table to extract a whitelist containing the BLE - * addresses and IRKs of bonded devices. - * - * @param[in/out] p_whitelist - * (on input) p_whitelist->addr_count and - * p_whitelist->irk_count specify the maximum number of - * addresses and IRKs added to the whitelist structure. - * (on output) *p_whitelist is a whitelist containing the - * addresses and IRKs of the bonded devices. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist); -#endif - -/** - * Function to test whether a BLE address is generated using an IRK. - * - * @param[in] p_addr - * Pointer to a BLE address. - * @param[in] p_irk - * Pointer to an IRK. - * - * @return True if p_addr can be generated using p_irk, false otherwise. - */ -bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - -/** - * Function to generate a private resolvable BLE address. - * - * @param[out] p_addr - * The output address. - * @param[in] p_irk - * A reference to a IRK. - * - * @note This function does not generate a secure address since the prand number in the - * resolvable address is not truly random. Therefore, the output of this function - * is only meant to be used by the application internally but never exported. - */ -void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address); - -#if (NRF_SD_BLE_API_VERSION >= 3) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList); -#endif - -#endif /* _BTLE_SECURITY_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp deleted file mode 100644 index 09afdebe5c..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle_security_pm.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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. - */ - -#if defined(S130) || defined(S132) || defined(S140) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "peer_manager.h" -#include "id_manager.h" -#include "fds.h" -} - -#include "btle_security.h" -#if 0 - -static bool initialized = false; - -static void pm_handler(pm_evt_t const *p_event); -static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing. -volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API. - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - if (enableBonding) { - securityParameters.kdist_own.enc = 1; - securityParameters.kdist_own.id = 1; - } else { - securityParameters.kdist_own.enc = 0; - securityParameters.kdist_own.id = 0; - } - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_register(pm_handler); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } - - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - - async_ret_code = NRF_ERROR_BUSY; - - rc = pm_peers_delete(); // it is asynhronous API - - if (rc == NRF_SUCCESS) - { - // waiting for respond from pm_handler - while (async_ret_code == NRF_ERROR_BUSY) { - // busy-loop - } - - rc = async_ret_code; - } - - switch (rc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - pm_conn_sec_status_t conn_sec_status; - - rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status); - - if (rc == NRF_SUCCESS) - { - if (conn_sec_status.encrypted) { - *securityStatusP = SecurityManager::ENCRYPTED; - } - else if (conn_sec_status.connected) { - if (_enc_in_progress) { - *securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS; - } - else { - *securityStatusP = SecurityManager::NOT_ENCRYPTED; - } - } - - return BLE_ERROR_NONE; - } - - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - return BLE_ERROR_INVALID_PARAM; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ret_code_t rc; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 0; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 1; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_conn_secure(connectionHandle, false); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - - -void pm_handler(pm_evt_t const *p_event) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - ret_code_t err_code; - SecurityManager::SecurityMode_t resolvedSecurityMode; - - switch (p_event->evt_id) { - case PM_EVT_CONN_SEC_START: /* started */ { - const ble_gap_sec_params_t *peerParams = &securityParameters; - securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - _enc_in_progress = true; - break; - } - case PM_EVT_CONN_SEC_SUCCEEDED: - // Update the rank of the peer. - if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) - { - err_code = pm_peer_rank_highest(p_event->peer_id); - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, - SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t - - ble_gap_conn_sec_t conn_sec; - sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec); - - resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - - switch (conn_sec.sec_mode.sm) { - case 1: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode); - - _enc_in_progress = false; - break; - - case PM_EVT_CONN_SEC_FAILED: - SecurityManager::SecurityCompletionStatus_t securityCompletionStatus; - - if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) { - securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED; - } else { - securityCompletionStatus = - (SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error; - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus); - - _enc_in_progress = false; - break; - - case PM_EVT_BONDED_PEER_CONNECTED: - pm_peer_rank_highest(p_event->peer_id); - break; - - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - securityManager.processSecurityContextStoredEvent(p_event->conn_handle); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - break; - - case PM_EVT_PEERS_DELETE_SUCCEEDED: - async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_PEERS_DELETE_FAILED: - async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_STORAGE_FULL: - // Run garbage collection on the flash. - err_code = fds_gc(); - if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) - { - // Retry. - } - else - { - APP_ERROR_CHECK(err_code); - } - break;//PM_EVT_STORAGE_FULL - - case PM_EVT_CONN_SEC_CONFIG_REQ:{ - // A connected peer (central) is trying to pair, but the Peer Manager already has a bond - // for that peer. Setting allow_repairing to false rejects the pairing request. - // If this event is ignored (pm_conn_sec_config_reply is not called in the event - // handler), the Peer Manager assumes allow_repairing to be false. - pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; - pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config); - } - break;//PM_EVT_CONN_SEC_CONFIG_REQ - - default: - break; - } -} - -#endif -#if (NRF_SD_BLE_API_VERSION <= 2) -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} -#endif -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} -#if 0 -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} - - -#if (NRF_SD_BLE_API_VERSION >= 3) -ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) -{ - pm_peer_id_t peer_id; - ret_code_t ret; - pm_peer_data_bonding_t bond_data; - - addrList.size = 0; - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - /** - * Fill addresses list: - * Copy addresses from bond table, or - * for every private resolvable address in the bond table generate the resolvable address. - */ - while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - btle_generateResolvableAddress(bond_data.peer_ble_id.id_info, - (ble_gap_addr_t &) addrList.addresses[addrList.size].address); - } else { - memcpy(&addrList.addresses[addrList.size].address, - &bond_data.peer_ble_id.id_addr_info.addr, - sizeof(addrList.addresses[0].address)); - } - - addrList.addresses[addrList.size].type = static_cast (bond_data.peer_ble_id.id_addr_info.addr_type); - - addrList.size++; - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - return BLE_ERROR_NONE; -} -#endif - -#endif // defined(S130) || defined(S132) || defined(S140) -#endif \ No newline at end of file diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index 33bb4dda98..4ca36c7b43 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -26,11 +26,6 @@ #include "ble_advdata.h" #include "headers/nrf_ble_hci.h" -#if (NRF_SD_BLE_API_VERSION >= 3) - #include "peer_manager.h" - #include "peer_data_storage.h" -#endif - void radioNotificationStaticCallback(bool param) { nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); @@ -962,75 +957,7 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const /**************************************************************************/ ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) { - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[1]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - if (securityManager.hasInitialized()) { - /* We do not care about the addresses, set the count to 0 */ - whitelistFromBondTable.addr_count = 0; - /* The Nordic SDK will return a failure if we set pp_addr to NULL */ - whitelistFromBondTable.pp_addrs = addressPtr; - /* We want all the IRKs we can get because we do not know which ones match the addresses */ - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - /* Use the security manager to get the IRKs from the bond table */ - ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - return error; - } - } else { - /** - * If there is no security manager then we cannot access the bond table, - * so disable IRK matching - */ - whitelistFromBondTable.addr_count = 0; - whitelistFromBondTable.irk_count = 0; - } - - /** - * For every private resolvable address in the local whitelist check if - * there is an IRK for said address in the bond table and add it to the - * local IRK list. - */ - whitelist.irk_count = 0; - whitelist.addr_count = 0; - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - /* Test if there is a matching IRK for this private resolvable address */ - for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { - /* Found the corresponding IRK, add it to our local whitelist */ - whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; - whitelist.irk_count++; - /* Make sure we do not look at this IRK again */ - if (j != whitelistFromBondTable.irk_count - 1) { - /** - * This is not the last IRK, so replace the pointer - * with the last pointer in the array - */ - whitelistFromBondTable.pp_irks[j] = - whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; - } - /** - * If the IRK is the last pointer in the array simply - * decrement the total IRK count - */ - whitelistFromBondTable.irk_count--; - break; - } - } - } else { - /* Include the address into the whitelist */ - whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; - whitelist.addr_count++; - } - } - - return BLE_ERROR_NONE; + return BLE_ERROR_NOT_IMPLEMENTED; } #endif @@ -1049,88 +976,7 @@ ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) { - using ble::pal::vendor::nordic::nRF5xSecurityManager; - - pm_peer_id_t peer_id; - - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - - uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE]; - - memset(irk_found, 0x00, sizeof(irk_found)); - - - gapAdrHelper.identities_cnt = 0; - - - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - /** - * Build identities list: - * For every private resolvable address in the bond table check if - * there is maching address in th provided whitelist. - */ - while (peer_id != PM_PEER_ID_INVALID) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - - //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; - if (btle_matchAddressAndIrk(address, irk)) - { - // Copy data to the buffer. - memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - gapAdrHelper.identities_cnt++; - - irk_found[i] = 1; // don't look at this address again - } - } - } - } - } - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - gapAdrHelper.addrs_cnt = 0; - - /** - * Build whitelist from the rest of addresses (explicit addresses) - */ - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t)); - gapAdrHelper.addrs[i].addr_id_peer = 0; - gapAdrHelper.addrs_cnt++; - } - } - - return BLE_ERROR_NONE; + BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index 0111ea1eb8..492498ead8 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -167,12 +167,13 @@ ble_error_t nRF5xSecurityManager::slave_security_request( // ble_error_t nRF5xSecurityManager::enable_encryption( - connection_handle_t connection, - const ltk_t <k, - const rand_t &rand, - const ediv_t &ediv, - bool mitm -) { + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm + ) +{ ble_gap_master_id_t master_id; ble_gap_enc_info_t enc_info; @@ -180,7 +181,30 @@ ble_error_t nRF5xSecurityManager::enable_encryption( memcpy(&master_id.ediv, ediv.data(), ediv.size()); memcpy(enc_info.ltk, ltk.data(), ltk.size()); - enc_info.lesc = _use_secure_connections; + enc_info.lesc = false; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm +) +{ + ble_gap_master_id_t master_id = {0}; + ble_gap_enc_info_t enc_info; + + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = true; enc_info.auth = mitm; enc_info.ltk_len = ltk.size(); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 8ae980d488..1cc4a1126d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -145,7 +145,7 @@ public: connection_handle_t connection, const ltk_t <k, bool mitm - ); + ) ; /** * @see ::ble::pal::SecurityManager::encrypt_data diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xSecurityManager.h deleted file mode 100644 index 0e901b5701..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xSecurityManager.h +++ /dev/null @@ -1,194 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 __NRF51822_SECURITY_MANAGER_H__ -#define __NRF51822_SECURITY_MANAGER_H__ - -#include - -#include "nRF5xGap.h" -#include "ble/SecurityManager.h" -#include "btle_security.h" - -class nRF5xSecurityManager : public SecurityManager -{ -public: - /* Functions that must be implemented from SecurityManager */ - virtual ble_error_t init(bool enableBonding, - bool requireMITM, - SecurityIOCapabilities_t iocaps, - const Passkey_t passkey) { - return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); - } - - virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { - return btle_getLinkSecurity(connectionHandle, securityStatusP); - } - - virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) { - return btle_setLinkSecurity(connectionHandle, securityMode); - } - - virtual ble_error_t purgeAllBondingState(void) { - return btle_purgeAllBondingState(); - } -#if (NRF_SD_BLE_API_VERSION <= 2) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - uint8_t i; - - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - /* Initialize the structure so that we get as many addreses as the whitelist can hold */ - whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_addrs = addressPtr; - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - addresses.size = 0; - return error; - } - - /* Put all the addresses in the structure */ - for (i = 0; i < whitelistFromBondTable.addr_count; ++i) { - if (i >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size = i; - return BLE_ERROR_NONE; - } - memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t)); - } - - /* Update the current address count */ - addresses.size = i; - - /* The assumption here is that the underlying implementation of - * createWhitelistFromBondTable() will not return the private resolvable - * addresses (which is the case in the SoftDevice). Rather it returns the - * IRKs, so we need to generate the private resolvable address by ourselves. - */ - for (i = 0; i < whitelistFromBondTable.irk_count; ++i) { - if (i + addresses.size >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size += i; - return BLE_ERROR_NONE; - } - btle_generateResolvableAddress( - *whitelistFromBondTable.pp_irks[i], - (ble_gap_addr_t &) addresses.addresses[i + addresses.size] - ); - } - - /* Update the current address count */ - addresses.size += i; - - return BLE_ERROR_NONE; - } -#else // -> NRF_SD_BLE_API_VERSION >= 3 - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - return btle_getAddressesFromBondTable(addresses); - } -#endif // #if (NRF_SD_BLE_API_VERSION <= 2) - - - - /** - * @brief Clear nRF5xSecurityManager's state. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t reset(void) - { - if (SecurityManager::reset() != BLE_ERROR_NONE) { - return BLE_ERROR_INVALID_STATE; - } - - return BLE_ERROR_NONE; - } - - bool hasInitialized(void) const { - return btle_hasInitializedSecurity(); - } - -public: - /* - * Allow instantiation from nRF5xn when required. - */ - friend class nRF5xn; - - nRF5xSecurityManager() { - /* empty */ - } - -private: - nRF5xSecurityManager(const nRF5xSecurityManager &); - const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &); - -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * Expose an interface that allows us to query the SoftDevice bond table - * and extract a whitelist. - */ - ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const { - return btle_createWhitelistFromBondTable(&whitelistFromBondTable); - } -#endif - /* - * Given a BLE address and a IRK this function check whether the address - * can be generated from the IRK. To do so, this function uses the hash - * function and algorithm described in the Bluetooth low Energy - * Specification. Internally, Nordic SDK functions are used. - */ - bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const { - return btle_matchAddressAndIrk(address, irk); - } - - /* - * Give nRF5xGap access to createWhitelistFromBondTable() and - * matchAddressAndIrk() - */ - friend class nRF5xGap; -}; - -#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ From 5f460c09afe54a0cce3534c3cd659a0470ae269d Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 2 Mar 2018 15:48:29 +0000 Subject: [PATCH 003/274] handling OOB data generation and verification now pushed down to PAL level --- .../ble/generic/GenericSecurityManager.h | 58 +------- .../FEATURE_BLE/ble/pal/MemorySecurityDB.h | 20 --- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 82 ++++++------ features/FEATURE_BLE/ble/pal/SecurityDb.h | 27 ---- .../source/generic/GenericSecurityManager.cpp | 126 ++---------------- .../TARGET_CORDIO/CordioPalSecurityManager.h | 28 +++- .../source/CordioPalSecurityManager.cpp | 23 +++- 7 files changed, 95 insertions(+), 269 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index ec9ae717b0..322cef4b5d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -238,8 +238,7 @@ public: _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), _legacy_pairing_allowed(true), - _master_sends_keys(false), - _public_keys_generated(false) { + _master_sends_keys(false) { _pal.set_event_handler(this); } @@ -321,17 +320,6 @@ private: const csrk_t *csrk ); -#if defined(MBEDTLS_CMAC_C) - /** - * Generate local OOB data to be sent to the application which sends it to the peer. - * - * @param[in] connectionHandle Handle to identify the connection. - */ - void generate_secure_connections_oob( - connection_handle_t connection - ); -#endif - /** * Updates the entry for the connection with OOB data presence. * @@ -341,26 +329,6 @@ private: connection_handle_t connection ); -#if defined(MBEDTLS_CMAC_C) - /** - * Calculate the confirmation value for secure connections OOB data based - * on local public key and a random number. - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.2.6 - - * @param[in] U public key x component - * @param[in] V public key y component - * @param[in] X random number - * @param[out] confirm confirmation value - * @return true if cryptography functioned worked - */ - static bool crypto_toolbox_f4( - const public_key_t &U, - const public_key_t &V, - const oob_lesc_value_t &X, - oob_confirm_t &confirm - ); -#endif - /** * Set the MITM protection setting on the database entry * @@ -477,13 +445,6 @@ private: bool _pairing_authorisation_required; bool _legacy_pairing_allowed; bool _master_sends_keys; - bool _public_keys_generated; - - /** There is always only one OOB data set stored at a time */ - address_t _peer_sc_oob_address; - oob_lesc_value_t _peer_sc_oob_random; - oob_confirm_t _peer_sc_oob_confirm; - oob_lesc_value_t _local_sc_oob_random; static const size_t MAX_CONTROL_BLOCKS = 5; ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS]; @@ -593,25 +554,18 @@ public: connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_oob_data_verification_request + /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ); //////////////////////////////////////////////////////////////////////////// // Keys // - /** @copydoc ble::pal::SecurityManager::on_public_key_generated - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ); - /** @copydoc ble::pal::SecurityManager::on_secure_connections_ltk_generated */ virtual void on_secure_connections_ltk_generated( diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index bde58a186a..a9ae337d03 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -240,24 +240,6 @@ public: _local_csrk = csrk; } - /* public key */ - - virtual const public_key_coord_t& get_public_key_x() { - return _public_key_x; - } - - virtual const public_key_coord_t& get_public_key_y() { - return _public_key_y; - } - - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) { - _public_key_x = public_key_x; - _public_key_y = public_key_y; - } - /* list management */ virtual entry_handle_t open_entry( @@ -362,8 +344,6 @@ private: entry_t _entries[MAX_ENTRIES]; SecurityEntryIdentity_t _local_identity; csrk_t _local_csrk; - public_key_coord_t _public_key_x; - public_key_coord_t _public_key_y; }; } /* namespace pal */ diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 3f51299f9b..7f8903fa07 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -371,7 +371,7 @@ public: * Request OOB data from the user application. * * @param[in] connection connection handle - * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_request_reply * or a cancellation of the procedure. */ virtual void on_legacy_pairing_oob_request( @@ -379,32 +379,24 @@ public: ) = 0; /** - * Request OOB data to be verified against received public keys. + * Send OOB data to the application for transport to the peer. * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) + * @param[in] address address of the local device + * @param[in] random random number used to generate the confirmation + * @param[in] confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ) = 0; //////////////////////////////////////////////////////////////////////////// // Keys // - /** - * Provide the local public key. - * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - /** * Store the results of key generation of the stage 2 of secure connections pairing * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.6.5 @@ -863,14 +855,6 @@ public: const csrk_t &csrk ) = 0; - /** - * Generate the Public key. This will also generate the private key. - * Public key will be returned as an event handler callback when it's ready. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure - */ - virtual ble_error_t generate_public_key() = 0; - //////////////////////////////////////////////////////////////////////////// // Authentication // @@ -931,7 +915,7 @@ public: * @param[in] oob_data pointer to out of band data * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) = 0; @@ -963,20 +947,38 @@ public: ) = 0; /** - * Notify the stack that the OOB data has been verified and supply the peer's random number. - * If the verification failed this will not be called and cancel_pairing will be called instead. + * Generate local OOB data to be sent to the application which sends it to the peer. * - * @param[in] connection connection handle - * @param[in] local_random random number sent from the local device to be used in further - * calculations by the stack, set to 0 if peer reported no OOB present - * @param[in] peer_random random number from the peer to be used in further - * calculations by the stack, set to 0 if no OOB data received - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @param[in] connectionHandle Handle to identify the connection. */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + virtual ble_error_t generate_secure_connections_oob( + connection_handle_t connection + ) = 0; + + /** + * Supply the stack with the OOB data for secure connections. + * + * @param[in] address address of the peer device this data comes from + * @param[in] random random number used to generate the confirmation + * @param[in] confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + virtual ble_error_t secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm + ) = 0; + + /** + * Supply the stack with the OOB data for secure connections. + * + * @param[in] address address of the peer device oob data is needed for + * @return True if oob data present, false if not or if the functionality + * is not implemented. + */ + virtual bool is_secure_connectinos_oob_present( + const address_t &address ) = 0; /* Entry points for the underlying stack to report events back to the user. */ diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 39f4729953..52dd3a8646 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -286,33 +286,6 @@ public: */ virtual void set_local_csrk(const csrk_t &csrk) = 0; - /* public keys */ - - /** - * Return local public key. - * - * @return ref to x component of public key - */ - virtual const public_key_coord_t& get_public_key_x() = 0; - - /** - * Return local public key. - * - * @return ref to y component of public key - */ - virtual const public_key_coord_t& get_public_key_y() = 0; - - /** - * Set local public key. - * - * @param[in] public_key_x new public key value of the x coordinate - * @param[in] public_key_y new public key value of the y coordinate - */ - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - /* list management */ /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 1568f11fb2..bbf75c6a77 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -17,9 +17,6 @@ #include "ble/SecurityManager.h" #include "ble/pal/PalSecurityManager.h" #include "ble/generic/GenericSecurityManager.h" -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif using ble::pal::advertising_peer_address_type_t; using ble::pal::AuthenticationMask; @@ -71,14 +68,11 @@ ble_error_t GenericSecurityManager::init( _connection_monitor.set_connection_event_handler(this); _pal.set_event_handler(this); - _pal.generate_public_key(); - return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::reset(void) { _db.sync(); - _public_keys_generated = false; SecurityManager::reset(); return BLE_ERROR_NONE; @@ -519,11 +513,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; -#if defined(MBEDTLS_CMAC_C) - if (_public_keys_generated) { - generate_secure_connections_oob(connection); - } -#endif + _pal.generate_secure_connections_oob(connection); return BLE_ERROR_NONE; } @@ -562,7 +552,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( return BLE_ERROR_INVALID_PARAM; } - return _pal.legacy_pairing_oob_data_request_reply(cb->connection, *tk); + return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk); } return BLE_ERROR_NONE; } @@ -573,10 +563,7 @@ ble_error_t GenericSecurityManager::oobReceived( const oob_confirm_t *confirm ) { if (address && random && confirm) { - _peer_sc_oob_address = *address; - _peer_sc_oob_random = *random; - _peer_sc_oob_confirm = *confirm; - return BLE_ERROR_NONE; + return _pal.secure_connections_oob_received(*address, *random, *confirm); } return BLE_ERROR_INVALID_PARAM; @@ -697,40 +684,6 @@ void GenericSecurityManager::return_csrk_cb( ); } -#if defined(MBEDTLS_CMAC_C) -void GenericSecurityManager::generate_secure_connections_oob( - connection_handle_t connection -) { - oob_confirm_t confirm; - oob_lesc_value_t random; - - ControlBlock_t *cb = get_control_block(connection); - if (!cb) { - return; - } - - ble_error_t ret = get_random_data(random.buffer(), random.size()); - if (ret != BLE_ERROR_NONE) { - return; - } - - crypto_toolbox_f4( - _db.get_public_key_x(), - _db.get_public_key_y(), - random, - confirm - ); - - eventHandler->oobGenerated( - &cb->local_address, - &random, - &confirm - ); - - _local_sc_oob_random = random; -} -#endif - void GenericSecurityManager::update_oob_presence(connection_handle_t connection) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { @@ -743,45 +696,10 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) cb->oob_present = cb->attempt_oob; if (_default_authentication.get_secure_connections()) { - cb->oob_present = false; -#if defined(MBEDTLS_CMAC_C) - if (cb->peer_address == _peer_sc_oob_address) { - cb->oob_present = true; - } -#endif + cb->oob_present = _pal.is_secure_connectinos_oob_present(cb->peer_address); } } -#if defined(MBEDTLS_CMAC_C) -bool GenericSecurityManager::crypto_toolbox_f4( - const public_key_coord_t& U, - const public_key_coord_t& V, - const oob_lesc_value_t& X, - oob_confirm_t& confirm -) { - - mbedtls_cipher_context_t context; - const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); - const unsigned char Z = 0; - bool success = false; - - mbedtls_cipher_init(&context); - - /* it's either this chaining or a goto */ - if (mbedtls_cipher_setup(&context, info) == 0 - && mbedtls_cipher_cmac_starts(&context, X.data(), 128) == 0 - && mbedtls_cipher_cmac_update(&context, U.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, V.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, &Z, 1) == 0 - && mbedtls_cipher_cmac_finish(&context, &confirm[0]) == 0) { - success = true; - } - - mbedtls_cipher_free(&context); - return success; -} -#endif - void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) { ControlBlock_t *cb = get_control_block(connection); if (cb) { @@ -1031,44 +949,18 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c eventHandler->legacyPairingOobRequest(connection); } -void GenericSecurityManager::on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y +void GenericSecurityManager::on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ) { -#if defined(MBEDTLS_CMAC_C) - ControlBlock_t *cb = get_control_block(connection); - - oob_confirm_t confirm_verify; - - crypto_toolbox_f4( - peer_public_key_x, - peer_public_key_y, - _peer_sc_oob_random, - confirm_verify - ); - - if (cb && (cb->peer_address == _peer_sc_oob_address) - && (confirm_verify == _peer_sc_oob_confirm)) { - _pal.oob_data_verified(connection, _local_sc_oob_random, _peer_sc_oob_random); - } else { - _pal.cancel_pairing(connection, pairing_failure_t::CONFIRM_VALUE_FAILED); - } -#endif + eventHandler->oobGenerated(&local_address, &random, &confirm); } //////////////////////////////////////////////////////////////////////////// // Keys // -void GenericSecurityManager::on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y -) { - _db.set_public_key(public_key_x, public_key_y); - _public_keys_generated = true; -} - void GenericSecurityManager::on_secure_connections_ltk_generated( connection_handle_t connection, const ltk_t <k diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 10b0a0922b..ea71de9bdf 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -273,9 +273,9 @@ public: ); /** - * @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ); @@ -295,12 +295,26 @@ public: ); /** - * @see ::ble::pal::SecurityManager::oob_data_verified + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + virtual ble_error_t generate_secure_connections_oob( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_received + */ + virtual ble_error_t secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm + ); + + /** + * @see ::ble::pal::SecurityManager::is_secure_connectinos_oob_present + */ + virtual bool is_secure_connectinos_oob_present( + const address_t &address ); // singleton of the ARM Cordio Security Manager diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index a682561335..5ce8a7d00d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -364,7 +364,7 @@ ble_error_t CordioSecurityManager::passkey_request_reply( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::legacy_pairing_oob_data_request_reply( +ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) { @@ -394,15 +394,26 @@ ble_error_t CordioSecurityManager::send_keypress_notification( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random +ble_error_t CordioSecurityManager::generate_secure_connections_oob( + connection_handle_t connection ) { - // FIXME: return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t CordioSecurityManager::secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +bool CordioSecurityManager::is_secure_connectinos_oob_present( + const address_t &address +) { + return false; +} + CordioSecurityManager& CordioSecurityManager::get_security_manager() { static CordioSecurityManager _security_manager; From b8ba99a18448d414a95cf8b7b6080bf17f2e9f9e Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 2 Mar 2018 15:48:29 +0000 Subject: [PATCH 004/274] handling OOB data generation and verification now pushed down to PAL level --- .../ble/generic/GenericSecurityManager.h | 58 +------- .../FEATURE_BLE/ble/pal/MemorySecurityDB.h | 20 --- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 82 ++++++------ features/FEATURE_BLE/ble/pal/SecurityDb.h | 27 ---- .../source/generic/GenericSecurityManager.cpp | 126 ++---------------- .../TARGET_CORDIO/CordioPalSecurityManager.h | 28 +++- .../source/CordioPalSecurityManager.cpp | 23 +++- 7 files changed, 95 insertions(+), 269 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index ec9ae717b0..322cef4b5d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -238,8 +238,7 @@ public: _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), _legacy_pairing_allowed(true), - _master_sends_keys(false), - _public_keys_generated(false) { + _master_sends_keys(false) { _pal.set_event_handler(this); } @@ -321,17 +320,6 @@ private: const csrk_t *csrk ); -#if defined(MBEDTLS_CMAC_C) - /** - * Generate local OOB data to be sent to the application which sends it to the peer. - * - * @param[in] connectionHandle Handle to identify the connection. - */ - void generate_secure_connections_oob( - connection_handle_t connection - ); -#endif - /** * Updates the entry for the connection with OOB data presence. * @@ -341,26 +329,6 @@ private: connection_handle_t connection ); -#if defined(MBEDTLS_CMAC_C) - /** - * Calculate the confirmation value for secure connections OOB data based - * on local public key and a random number. - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.2.6 - - * @param[in] U public key x component - * @param[in] V public key y component - * @param[in] X random number - * @param[out] confirm confirmation value - * @return true if cryptography functioned worked - */ - static bool crypto_toolbox_f4( - const public_key_t &U, - const public_key_t &V, - const oob_lesc_value_t &X, - oob_confirm_t &confirm - ); -#endif - /** * Set the MITM protection setting on the database entry * @@ -477,13 +445,6 @@ private: bool _pairing_authorisation_required; bool _legacy_pairing_allowed; bool _master_sends_keys; - bool _public_keys_generated; - - /** There is always only one OOB data set stored at a time */ - address_t _peer_sc_oob_address; - oob_lesc_value_t _peer_sc_oob_random; - oob_confirm_t _peer_sc_oob_confirm; - oob_lesc_value_t _local_sc_oob_random; static const size_t MAX_CONTROL_BLOCKS = 5; ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS]; @@ -593,25 +554,18 @@ public: connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_oob_data_verification_request + /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ); //////////////////////////////////////////////////////////////////////////// // Keys // - /** @copydoc ble::pal::SecurityManager::on_public_key_generated - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ); - /** @copydoc ble::pal::SecurityManager::on_secure_connections_ltk_generated */ virtual void on_secure_connections_ltk_generated( diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index bde58a186a..a9ae337d03 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -240,24 +240,6 @@ public: _local_csrk = csrk; } - /* public key */ - - virtual const public_key_coord_t& get_public_key_x() { - return _public_key_x; - } - - virtual const public_key_coord_t& get_public_key_y() { - return _public_key_y; - } - - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) { - _public_key_x = public_key_x; - _public_key_y = public_key_y; - } - /* list management */ virtual entry_handle_t open_entry( @@ -362,8 +344,6 @@ private: entry_t _entries[MAX_ENTRIES]; SecurityEntryIdentity_t _local_identity; csrk_t _local_csrk; - public_key_coord_t _public_key_x; - public_key_coord_t _public_key_y; }; } /* namespace pal */ diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 3f51299f9b..7f8903fa07 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -371,7 +371,7 @@ public: * Request OOB data from the user application. * * @param[in] connection connection handle - * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_request_reply * or a cancellation of the procedure. */ virtual void on_legacy_pairing_oob_request( @@ -379,32 +379,24 @@ public: ) = 0; /** - * Request OOB data to be verified against received public keys. + * Send OOB data to the application for transport to the peer. * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) + * @param[in] address address of the local device + * @param[in] random random number used to generate the confirmation + * @param[in] confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ - virtual void on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y + virtual void on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ) = 0; //////////////////////////////////////////////////////////////////////////// // Keys // - /** - * Provide the local public key. - * - * @param[in] public_key_x newly generated public key (x coordinate) - * @param[in] public_key_y newly generated public key (y coordinate) - */ - virtual void on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - /** * Store the results of key generation of the stage 2 of secure connections pairing * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.6.5 @@ -863,14 +855,6 @@ public: const csrk_t &csrk ) = 0; - /** - * Generate the Public key. This will also generate the private key. - * Public key will be returned as an event handler callback when it's ready. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure - */ - virtual ble_error_t generate_public_key() = 0; - //////////////////////////////////////////////////////////////////////////// // Authentication // @@ -931,7 +915,7 @@ public: * @param[in] oob_data pointer to out of band data * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) = 0; @@ -963,20 +947,38 @@ public: ) = 0; /** - * Notify the stack that the OOB data has been verified and supply the peer's random number. - * If the verification failed this will not be called and cancel_pairing will be called instead. + * Generate local OOB data to be sent to the application which sends it to the peer. * - * @param[in] connection connection handle - * @param[in] local_random random number sent from the local device to be used in further - * calculations by the stack, set to 0 if peer reported no OOB present - * @param[in] peer_random random number from the peer to be used in further - * calculations by the stack, set to 0 if no OOB data received - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @param[in] connectionHandle Handle to identify the connection. */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + virtual ble_error_t generate_secure_connections_oob( + connection_handle_t connection + ) = 0; + + /** + * Supply the stack with the OOB data for secure connections. + * + * @param[in] address address of the peer device this data comes from + * @param[in] random random number used to generate the confirmation + * @param[in] confirm confirmation value to be use for authentication + * in secure connections pairing + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + virtual ble_error_t secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm + ) = 0; + + /** + * Supply the stack with the OOB data for secure connections. + * + * @param[in] address address of the peer device oob data is needed for + * @return True if oob data present, false if not or if the functionality + * is not implemented. + */ + virtual bool is_secure_connectinos_oob_present( + const address_t &address ) = 0; /* Entry points for the underlying stack to report events back to the user. */ diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 39f4729953..52dd3a8646 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -286,33 +286,6 @@ public: */ virtual void set_local_csrk(const csrk_t &csrk) = 0; - /* public keys */ - - /** - * Return local public key. - * - * @return ref to x component of public key - */ - virtual const public_key_coord_t& get_public_key_x() = 0; - - /** - * Return local public key. - * - * @return ref to y component of public key - */ - virtual const public_key_coord_t& get_public_key_y() = 0; - - /** - * Set local public key. - * - * @param[in] public_key_x new public key value of the x coordinate - * @param[in] public_key_y new public key value of the y coordinate - */ - virtual void set_public_key( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y - ) = 0; - /* list management */ /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 1568f11fb2..bbf75c6a77 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -17,9 +17,6 @@ #include "ble/SecurityManager.h" #include "ble/pal/PalSecurityManager.h" #include "ble/generic/GenericSecurityManager.h" -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif using ble::pal::advertising_peer_address_type_t; using ble::pal::AuthenticationMask; @@ -71,14 +68,11 @@ ble_error_t GenericSecurityManager::init( _connection_monitor.set_connection_event_handler(this); _pal.set_event_handler(this); - _pal.generate_public_key(); - return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::reset(void) { _db.sync(); - _public_keys_generated = false; SecurityManager::reset(); return BLE_ERROR_NONE; @@ -519,11 +513,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; -#if defined(MBEDTLS_CMAC_C) - if (_public_keys_generated) { - generate_secure_connections_oob(connection); - } -#endif + _pal.generate_secure_connections_oob(connection); return BLE_ERROR_NONE; } @@ -562,7 +552,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( return BLE_ERROR_INVALID_PARAM; } - return _pal.legacy_pairing_oob_data_request_reply(cb->connection, *tk); + return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk); } return BLE_ERROR_NONE; } @@ -573,10 +563,7 @@ ble_error_t GenericSecurityManager::oobReceived( const oob_confirm_t *confirm ) { if (address && random && confirm) { - _peer_sc_oob_address = *address; - _peer_sc_oob_random = *random; - _peer_sc_oob_confirm = *confirm; - return BLE_ERROR_NONE; + return _pal.secure_connections_oob_received(*address, *random, *confirm); } return BLE_ERROR_INVALID_PARAM; @@ -697,40 +684,6 @@ void GenericSecurityManager::return_csrk_cb( ); } -#if defined(MBEDTLS_CMAC_C) -void GenericSecurityManager::generate_secure_connections_oob( - connection_handle_t connection -) { - oob_confirm_t confirm; - oob_lesc_value_t random; - - ControlBlock_t *cb = get_control_block(connection); - if (!cb) { - return; - } - - ble_error_t ret = get_random_data(random.buffer(), random.size()); - if (ret != BLE_ERROR_NONE) { - return; - } - - crypto_toolbox_f4( - _db.get_public_key_x(), - _db.get_public_key_y(), - random, - confirm - ); - - eventHandler->oobGenerated( - &cb->local_address, - &random, - &confirm - ); - - _local_sc_oob_random = random; -} -#endif - void GenericSecurityManager::update_oob_presence(connection_handle_t connection) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { @@ -743,45 +696,10 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) cb->oob_present = cb->attempt_oob; if (_default_authentication.get_secure_connections()) { - cb->oob_present = false; -#if defined(MBEDTLS_CMAC_C) - if (cb->peer_address == _peer_sc_oob_address) { - cb->oob_present = true; - } -#endif + cb->oob_present = _pal.is_secure_connectinos_oob_present(cb->peer_address); } } -#if defined(MBEDTLS_CMAC_C) -bool GenericSecurityManager::crypto_toolbox_f4( - const public_key_coord_t& U, - const public_key_coord_t& V, - const oob_lesc_value_t& X, - oob_confirm_t& confirm -) { - - mbedtls_cipher_context_t context; - const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); - const unsigned char Z = 0; - bool success = false; - - mbedtls_cipher_init(&context); - - /* it's either this chaining or a goto */ - if (mbedtls_cipher_setup(&context, info) == 0 - && mbedtls_cipher_cmac_starts(&context, X.data(), 128) == 0 - && mbedtls_cipher_cmac_update(&context, U.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, V.data(), 16) == 0 - && mbedtls_cipher_cmac_update(&context, &Z, 1) == 0 - && mbedtls_cipher_cmac_finish(&context, &confirm[0]) == 0) { - success = true; - } - - mbedtls_cipher_free(&context); - return success; -} -#endif - void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) { ControlBlock_t *cb = get_control_block(connection); if (cb) { @@ -1031,44 +949,18 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c eventHandler->legacyPairingOobRequest(connection); } -void GenericSecurityManager::on_oob_data_verification_request( - connection_handle_t connection, - const public_key_coord_t &peer_public_key_x, - const public_key_coord_t &peer_public_key_y +void GenericSecurityManager::on_secure_connections_oob_generated( + const address_t &local_address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm ) { -#if defined(MBEDTLS_CMAC_C) - ControlBlock_t *cb = get_control_block(connection); - - oob_confirm_t confirm_verify; - - crypto_toolbox_f4( - peer_public_key_x, - peer_public_key_y, - _peer_sc_oob_random, - confirm_verify - ); - - if (cb && (cb->peer_address == _peer_sc_oob_address) - && (confirm_verify == _peer_sc_oob_confirm)) { - _pal.oob_data_verified(connection, _local_sc_oob_random, _peer_sc_oob_random); - } else { - _pal.cancel_pairing(connection, pairing_failure_t::CONFIRM_VALUE_FAILED); - } -#endif + eventHandler->oobGenerated(&local_address, &random, &confirm); } //////////////////////////////////////////////////////////////////////////// // Keys // -void GenericSecurityManager::on_public_key_generated( - const public_key_coord_t &public_key_x, - const public_key_coord_t &public_key_y -) { - _db.set_public_key(public_key_x, public_key_y); - _public_keys_generated = true; -} - void GenericSecurityManager::on_secure_connections_ltk_generated( connection_handle_t connection, const ltk_t <k diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 10b0a0922b..ea71de9bdf 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -273,9 +273,9 @@ public: ); /** - * @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ); @@ -295,12 +295,26 @@ public: ); /** - * @see ::ble::pal::SecurityManager::oob_data_verified + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + virtual ble_error_t generate_secure_connections_oob( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_received + */ + virtual ble_error_t secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm + ); + + /** + * @see ::ble::pal::SecurityManager::is_secure_connectinos_oob_present + */ + virtual bool is_secure_connectinos_oob_present( + const address_t &address ); // singleton of the ARM Cordio Security Manager diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index a682561335..5ce8a7d00d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -364,7 +364,7 @@ ble_error_t CordioSecurityManager::passkey_request_reply( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::legacy_pairing_oob_data_request_reply( +ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ) { @@ -394,15 +394,26 @@ ble_error_t CordioSecurityManager::send_keypress_notification( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random +ble_error_t CordioSecurityManager::generate_secure_connections_oob( + connection_handle_t connection ) { - // FIXME: return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t CordioSecurityManager::secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +bool CordioSecurityManager::is_secure_connectinos_oob_present( + const address_t &address +) { + return false; +} + CordioSecurityManager& CordioSecurityManager::get_security_manager() { static CordioSecurityManager _security_manager; From 7c82e91981a5aa7d01591da502826b90b4a74607 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 9 Mar 2018 12:49:10 +0000 Subject: [PATCH 005/274] fixed typo --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index ea71de9bdf..d79c1c788c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -311,9 +311,9 @@ public: ); /** - * @see ::ble::pal::SecurityManager::is_secure_connectinos_oob_present + * @see ::ble::pal::SecurityManager::is_secure_connections_oob_present */ - virtual bool is_secure_connectinos_oob_present( + virtual bool is_secure_connections_oob_present( const address_t &address ); From 1f8c5c1231307a397e2775d25b21ce34cdf52752 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 9 Mar 2018 14:22:28 +0000 Subject: [PATCH 006/274] fixed typos --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 2 +- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 7f8903fa07..ac984ab0d8 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -977,7 +977,7 @@ public: * @return True if oob data present, false if not or if the functionality * is not implemented. */ - virtual bool is_secure_connectinos_oob_present( + virtual bool is_secure_connections_oob_present( const address_t &address ) = 0; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index bbf75c6a77..0e6cb57e5e 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -696,7 +696,7 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) cb->oob_present = cb->attempt_oob; if (_default_authentication.get_secure_connections()) { - cb->oob_present = _pal.is_secure_connectinos_oob_present(cb->peer_address); + cb->oob_present = _pal.is_secure_connections_oob_present(cb->peer_address); } } From 19bb13c8c5d5afd7a507b16b1a95f4737340a608 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 9 Mar 2018 14:56:37 +0000 Subject: [PATCH 007/274] one last typo --- .../targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 5ce8a7d00d..24e405ef65 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -408,7 +408,7 @@ ble_error_t CordioSecurityManager::secure_connections_oob_received( return BLE_ERROR_NOT_IMPLEMENTED; } -bool CordioSecurityManager::is_secure_connectinos_oob_present( +bool CordioSecurityManager::is_secure_connections_oob_present( const address_t &address ) { return false; From bd7be3d6438535197d6f862e23db23be785b2a55 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 17:56:59 +0000 Subject: [PATCH 008/274] BLE: qualification of SecurityManager types --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index ac984ab0d8..9e7ac94d16 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -27,10 +27,10 @@ namespace ble { namespace pal { -typedef SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; -typedef SecurityManager::SecurityMode_t SecurityMode_t; -typedef SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; -typedef SecurityManager::Keypress_t Keypress_t; +typedef ::SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; +typedef ::SecurityManager::SecurityMode_t SecurityMode_t; +typedef ::SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; +typedef ::SecurityManager::Keypress_t Keypress_t; /** * Key distribution as required by the SMP with convenient setters and getters, From 36ca6be69afc28f7a7adfe09870e9f54787415ff Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:04:47 +0000 Subject: [PATCH 009/274] BLE: Initialize the pal in GenericSecurityManager --- .gitignore | 2 ++ .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 88ff051ecc..7b85cc3417 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,5 @@ tags # Visual Studio Code .vscode/ + +features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 0e6cb57e5e..6ebe31ae95 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -39,6 +39,11 @@ ble_error_t GenericSecurityManager::init( const Passkey_t passkey, bool signing ) { + ble_error_t err = _pal.initialize(); + if (err) { + return err; + } + _db.restore(); _pal.set_io_capability((io_capability_t::type) iocaps); @@ -73,6 +78,7 @@ ble_error_t GenericSecurityManager::init( ble_error_t GenericSecurityManager::reset(void) { _db.sync(); + _pal.reset(); SecurityManager::reset(); return BLE_ERROR_NONE; From 38bee37804547d86812e7cff7ebeb5d6ac41e994 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:05:31 +0000 Subject: [PATCH 010/274] Cordio: remove generate_public_key from the security manager. --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index d79c1c788c..5a6e64106b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -195,11 +195,6 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); - /** - * @see ::ble::pal::SecurityManager::generate_public_key - */ - virtual ble_error_t generate_public_key(); - //////////////////////////////////////////////////////////////////////////// // Global parameters // From 5a2008211acc6d123ce92f1e82dbceca64ad1c02 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:06:22 +0000 Subject: [PATCH 011/274] Cordio: Implement missing functions for secure connection --- .../TARGET_CORDIO/CordioPalSecurityManager.h | 11 +++ .../source/CordioPalSecurityManager.cpp | 92 +++++++++++++++---- 2 files changed, 86 insertions(+), 17 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 5a6e64106b..9e66ed47b7 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -20,6 +20,8 @@ #include "ble/pal/PalSecurityManager.h" #include "wsf_types.h" #include "wsf_os.h" +#include "sec_api.h" +#include "smp_defs.h" namespace ble { namespace pal { @@ -321,6 +323,15 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; + bool _lesc_keys_generated; + uint8_t _public_key_x[SEC_ECC_KEY_LEN]; + bool _peer_oob_present; + address_t _peer_oob_address; + oob_lesc_value_t _peer_oob_random; + oob_confirm_t _peer_oob_confirm; + bool _own_oob_present; + uint8_t _confirm[SMP_CONFIRM_LEN]; + uint8_t _random[SMP_RAND_LEN]; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 24e405ef65..c78fae76c6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include "CordioPalSecurityManager.h" #include "dm_api.h" #include "smp_api.h" @@ -27,7 +29,16 @@ namespace cordio { CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), - _default_passkey(0) + _default_passkey(0), + _lesc_keys_generated(false), + _public_key_x(), + _peer_oob_present(false), + _peer_oob_address(), + _peer_oob_random(), + _peer_oob_confirm(), + _own_oob_present(false), + _confirm(), + _random() { } @@ -43,6 +54,16 @@ CordioSecurityManager::~CordioSecurityManager() ble_error_t CordioSecurityManager::initialize() { + // reset local state + _use_default_passkey = false; + _default_passkey = 0; + _lesc_keys_generated = false; + _peer_oob_present = false; + _own_oob_present = false; + + // generate a new set of keys + DmSecGenerateEccKeyReq(); + return BLE_ERROR_NONE; } @@ -53,6 +74,7 @@ ble_error_t CordioSecurityManager::terminate() ble_error_t CordioSecurityManager::reset() { + initialize(); return BLE_ERROR_NONE; } @@ -253,12 +275,6 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::generate_public_key() -{ - // FIXME - return BLE_ERROR_NOT_IMPLEMENTED; -} - //////////////////////////////////////////////////////////////////////////// // Global parameters // @@ -380,8 +396,8 @@ ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply( ble_error_t CordioSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { - // FIXME: - return BLE_ERROR_NOT_IMPLEMENTED; + DmSecCompareRsp(connection, confirmation); + return BLE_ERROR_NONE; } // FIXME: remove when declaration from the stack is available @@ -397,6 +413,13 @@ ble_error_t CordioSecurityManager::send_keypress_notification( ble_error_t CordioSecurityManager::generate_secure_connections_oob( connection_handle_t connection ) { + // Note: this is not tie to a connection; only one oob value is present in + // the pal. + + uint8_t oobLocalRandom[SMP_RAND_LEN]; + SecRand(oobLocalRandom, SMP_RAND_LEN); + DmSecCalcOobReq(oobLocalRandom, _public_key_x); + return BLE_ERROR_NOT_IMPLEMENTED; } @@ -405,13 +428,21 @@ ble_error_t CordioSecurityManager::secure_connections_oob_received( const oob_lesc_value_t &random, const oob_confirm_t &confirm ) { - return BLE_ERROR_NOT_IMPLEMENTED; + _peer_oob_present = true; + _peer_oob_address = address; + _peer_oob_random = random; + _peer_oob_confirm = confirm; + + return BLE_ERROR_NONE; } bool CordioSecurityManager::is_secure_connections_oob_present( const address_t &address ) { - return false; + if (!_peer_oob_present) { + return false; + } + return address == _peer_oob_address; } CordioSecurityManager& CordioSecurityManager::get_security_manager() @@ -421,8 +452,8 @@ CordioSecurityManager& CordioSecurityManager::get_security_manager() } bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { - SecurityManager::EventHandler* handler = - get_security_manager().get_event_handler(); + CordioSecurityManager& self = get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); if ((msg == NULL) || (handler == NULL)) { return false; @@ -484,6 +515,11 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { connection_handle_t connection = evt->hdr.param; if (evt->oob) { + // FIXME: Nothing in the API indicates if smp or sc OOB are + // requested. + // To set secure connection OOB: + // - DmSecSetOob(connection, oob_data) + // - DmSecAuthRsp(connection, 0, NULL) handler->on_legacy_pairing_oob_request(connection); } else if (evt->display) { if (get_security_manager()._use_default_passkey) { @@ -607,14 +643,36 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { return true; } - case DM_SEC_CALC_OOB_IND: + case DM_SEC_CALC_OOB_IND: { + dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg; + self._own_oob_present = true; + memcpy(self._confirm, evt->confirm, sizeof(_confirm)); + memcpy(self._random, evt->random, sizeof(_random)); + handler->on_secure_connections_oob_generated( + address_t(), /* which address should be used ??? */ + evt->random, + evt->confirm + ); return true; + } - case DM_SEC_ECC_KEY_IND: + case DM_SEC_ECC_KEY_IND: { + secEccMsg_t* evt = (secEccMsg_t*) msg; + DmSecSetEccKey(&evt->data.key); + memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(_public_key_x)); + self._lesc_keys_generated = true; return true; + } - case DM_SEC_COMPARE_IND: - return true; + case DM_SEC_COMPARE_IND: { + dmSecCnfIndEvt_t* evt = (dmSecCnfIndEvt_t*) msg; + handler->on_passkey_display( + /* connection */ evt->hdr.param, + DmSecGetCompareValue(evt->confirm) + ); + handler->on_confirmation_request(/* connection */ evt->hdr.param); + return true; + } case DM_SEC_KEYPRESS_IND: { dmSecKeypressIndEvt_t* evt = (dmSecKeypressIndEvt_t*) msg; From 1521dee77322392357402aa1a0c6d2be81a5a335 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 9 Mar 2018 18:06:56 +0000 Subject: [PATCH 012/274] add doxygen comment about OOB deneration cause bu setOOBDataUsage --- features/FEATURE_BLE/ble/SecurityManager.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index a01882959a..43a83e7fe7 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -736,7 +736,8 @@ public: // /** - * Enable OOB data usage during paring. + * Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will + * generate Secure Connections OOB data through oobGenerated(). * * @param[in] connectionHandle Handle to identify the connection. * @param[in] useOOB If set to true, authenticate using OOB data. From c3fd90430a4763b1514722cd77ee6ea8375b6de2 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 15 Mar 2018 09:32:58 +0000 Subject: [PATCH 013/274] BLE: Fix references to ConnectionEventMonitor::EventHandler --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp | 6 ++++-- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index 4ca36c7b43..5dfbd4a6bd 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -25,6 +25,7 @@ #include "common/common.h" #include "ble_advdata.h" #include "headers/nrf_ble_hci.h" +#include "ble/pal/ConnectionEventMonitor.h" void radioNotificationStaticCallback(bool param) { @@ -1045,8 +1046,9 @@ ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() } #endif -void nRF5xGap::set_connection_event_handler(ble::pal::ConnectionEventHandler *connection_event_handler) -{ +void nRF5xGap::set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler +) { _connection_event_handler = connection_event_handler; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h index 2e454403ef..e71fdbc937 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h @@ -55,8 +55,6 @@ extern "C" { void radioNotificationStaticCallback(bool param); -namespace ble { namespace pal { class ConnectionEventHandler; }} - /**************************************************************************/ /*! \brief @@ -260,7 +258,9 @@ public: /** @note Implements ConnectionEventMonitor. * @copydoc ConnectionEventMonitor::set_connection_event_handler */ - void set_connection_event_handler(ble::pal::ConnectionEventHandler *_connection_event_handler); + void set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler + ); /** * @copydoc ::Gap::processConnectionEvent @@ -285,7 +285,7 @@ public: uint16_t m_connectionHandle; - ble::pal::ConnectionEventHandler* _connection_event_handler; + ConnectionEventMonitor::EventHandler* _connection_event_handler; /* * Allow instantiation from nRF5xn when required. From 288abf528778cf87bdd6e6cf27606d94f9b290f9 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 15 Mar 2018 09:33:25 +0000 Subject: [PATCH 014/274] BLE: Add nRF5x constructor --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h index e71fdbc937..9a6973331c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h @@ -65,6 +65,8 @@ class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor { public: nRF5xGap(); + virtual ~nRF5xGap() { } + /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); From 761beafeb3d3fb9b03c26f4c981f4626fb6930b7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 15 Mar 2018 09:34:21 +0000 Subject: [PATCH 015/274] BLE: Complete nRF5xGap initialization list --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index 5dfbd4a6bd..e9e543e20e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -37,6 +37,9 @@ nRF5xGap::nRF5xGap() : Gap(), advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), whitelistAddressesSize(0), + whitelistAddresses(), + radioNotificationCallbackParam(false), + radioNotificationTimeout(), _connection_event_handler(NULL) { m_connectionHandle = BLE_CONN_HANDLE_INVALID; From 1638902341e2b3d2bb2d91cfd7ac57d282a6b28f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 15 Mar 2018 09:34:41 +0000 Subject: [PATCH 016/274] BLE: Whitespace fix --- .../TARGET_NRF5/source/nRF5xGap.cpp | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index e9e543e20e..bb38334b59 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -151,7 +151,7 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) { uint32_t err; ble_gap_adv_params_t adv_para = {0}; - + /* Make sure we support the advertising type */ if (params.getAdvertisingType() == GapAdvertisingParams::ADV_CONNECTABLE_DIRECTED) { /* ToDo: This requires a propery security implementation, etc. */ @@ -203,11 +203,11 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) return error; } } - + adv_para.p_whitelist = &whitelist; #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + /* Start Advertising */ @@ -216,7 +216,7 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) adv_para.fp = advertisingPolicyMode; adv_para.interval = params.getIntervalInADVUnits(); // advertising interval (in units of 0.625 ms) adv_para.timeout = params.getTimeout(); - + err = sd_ble_gap_adv_start(&adv_para); switch(err) { @@ -233,9 +233,9 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) { - + ble_gap_scan_params_t scanParams; - + #if (NRF_SD_BLE_API_VERSION <= 2) /* Allocate the stack's whitelist statically */ ble_gap_whitelist_t whitelist; @@ -254,16 +254,16 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) return error; } } - + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + scanParams.use_whitelist = scanningPolicyMode; scanParams.adv_dir_report = 0; #endif - + scanParams.active = scanningParams.getActiveScanning(); /**< If 1, perform active scanning (scan requests). */ scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ @@ -335,7 +335,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } ble_gap_scan_params_t scanParams ={0}; - + #if (NRF_SD_BLE_API_VERSION <= 2) /* Allocate the stack's whitelist statically */ ble_gap_whitelist_t whitelist; @@ -354,12 +354,12 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, return error; } } - + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ - + scanParams.use_whitelist = (whitelistAddressesSize) ? 1 : 0; if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) @@ -373,7 +373,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } else { addr.addr_id_peer = 0; } - + #endif if (scanParamsIn != NULL) { @@ -500,7 +500,7 @@ ble_error_t nRF5xGap::reset(void) /* Clear the internal whitelist */ whitelistAddressesSize = 0; - + return BLE_ERROR_NONE; } @@ -549,7 +549,7 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) ble_gap_privacy_params_t privacy_params = {0}; #endif - + ble_gap_addr_t dev_addr; /* When using Public or Static addresses, the cycle mode must be None. @@ -573,7 +573,7 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) { #if (NRF_SD_BLE_API_VERSION <= 2) cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; -#else +#else privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; privacy_params.private_addr_type = type; @@ -966,7 +966,7 @@ ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) #endif #if (NRF_SD_BLE_API_VERSION >= 3) - + /** * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. * @@ -976,17 +976,17 @@ ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) * are passed to the identities list (intended to be passed to the Softdevice). * * @param[out] gapAdrHelper Reference to the struct for storing settings. - */ + */ ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ +{ BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) { uint32_t retc; - + if (gapAdrHelper.identities_cnt == 0) { retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); } else { @@ -999,7 +999,7 @@ ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHe retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); } - + if (retc == NRF_SUCCESS) { if (gapAdrHelper.addrs_cnt == 0) { retc = sd_ble_gap_whitelist_set(NULL, 0); @@ -1014,7 +1014,7 @@ ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHe retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); } } - + switch(retc) { case NRF_SUCCESS: return BLE_ERROR_NONE; @@ -1028,7 +1028,7 @@ ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHe case NRF_ERROR_DATA_SIZE: case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. return BLE_ERROR_INVALID_PARAM; - + default: return BLE_ERROR_UNSPECIFIED; } @@ -1040,7 +1040,7 @@ ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() uint32_t err; err = getStackWhiteIdentityList(whiteAndIdentityList); - + if (err != BLE_ERROR_NONE) { return (ble_error_t)err; } @@ -1102,4 +1102,4 @@ void nRF5xGap::processDisconnectionEvent( handle, reason ); -} \ No newline at end of file +} From 5e8630dcc6000dd0ed77234e1f034282242b607e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 15 Mar 2018 11:24:31 +0000 Subject: [PATCH 017/274] BLE Nordic: Complete implementation of pal security manager --- .../source/nRF5xPalSecurityManager.cpp | 863 ++++++++++++------ .../source/nRF5xPalSecurityManager.h | 175 ++-- 2 files changed, 664 insertions(+), 374 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index 492498ead8..adf5572f58 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "nRF5xPalSecurityManager.h" #include "nrf_ble.h" #include "nrf_ble_gap.h" @@ -26,21 +27,63 @@ namespace nordic { namespace { static ble_error_t convert_sd_error(uint32_t err) { - // TODO: implementation - return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + case BLE_ERROR_INVALID_ROLE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NOT_SUPPORTED: + return BLE_ERROR_NOT_IMPLEMENTED; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_TIMEOUT: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_UNSPECIFIED; + } } } +enum pairing_role_t { + PAIRING_INITIATOR, + PAIRING_RESPONDER +}; + +struct nRF5xSecurityManager::pairing_control_block_t { + pairing_control_block_t* next; + connection_handle_t connection; + pairing_role_t role; + + // flags of the key present + KeyDistribution initiator_dist; + KeyDistribution responder_dist; + + // own keys + ble_gap_enc_key_t own_enc_key; + ble_gap_id_key_t own_id_key; + ble_gap_sign_info_t own_sign_key; + ble_gap_lesc_p256_pk_t own_pk; + + // peer keys + ble_gap_enc_key_t peer_enc_key; + ble_gap_id_key_t peer_id_key; + ble_gap_sign_info_t peer_sign_key; + ble_gap_lesc_p256_pk_t peer_pk; +}; nRF5xSecurityManager::nRF5xSecurityManager() : ::ble::pal::SecurityManager(), - _use_legacy_pairing(true), - _use_secure_connections(true), - _use_default_passkey(false), - _default_passkey(0), _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), _min_encryption_key_size(7), - _max_encryption_key_size(16) + _max_encryption_key_size(16), + _control_blocks(NULL) { } @@ -56,6 +99,7 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { + // FIXME: generate and set public and private keys return BLE_ERROR_NONE; } @@ -66,6 +110,7 @@ ble_error_t nRF5xSecurityManager::terminate() ble_error_t nRF5xSecurityManager::reset() { + // FIXME: reset public and private keys return BLE_ERROR_NONE; } @@ -78,7 +123,7 @@ ble_error_t nRF5xSecurityManager::reset() uint8_t nRF5xSecurityManager::read_resolving_list_capacity() { - // FIXME: implement + // FIXME: implement with privacy return 0; } @@ -87,6 +132,7 @@ ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( const address_t &peer_identity_address, const irk_t &peer_irk ) { + // FIXME: implement with privacy return BLE_ERROR_NOT_IMPLEMENTED; } @@ -94,34 +140,149 @@ ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address ) { + // FIXME: implement with privacy return BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xSecurityManager::clear_resolving_list() { + // FIXME: implement with privacy return BLE_ERROR_NOT_IMPLEMENTED; } +//////////////////////////////////////////////////////////////////////////// +// Pairing +// + + +ble_error_t nRF5xSecurityManager::send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + // allocate the control block required for the procedure completion + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_INITIATOR; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_RESPONDER; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ &security_params, + /* keys */ &keyset + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::cancel_pairing( + connection_handle_t connection, pairing_failure_t reason +) { + // this is the default path except when a key is expected to be enterred by + // the user. + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + reason.value() | 0x80, + /* sec params */ NULL, + /* keyset */ NULL + ); + + if (!err) { + return BLE_ERROR_NONE; + } + + // Failed because we're in the wrong state; try to cancel pairing with + // sd_ble_gap_auth_key_reply + if (err == NRF_ERROR_INVALID_STATE) { + err = sd_ble_gap_auth_key_reply( + connection, + /* key type */ BLE_GAP_AUTH_KEY_TYPE_NONE, + /* key */ NULL + ); + } + + return convert_sd_error(err); +} + //////////////////////////////////////////////////////////////////////////// // Feature support // -ble_error_t nRF5xSecurityManager::set_secure_connections_support( - bool enabled, bool secure_connections_only -) { - _use_secure_connections = enabled; - _use_legacy_pairing = !enabled || (enabled && !secure_connections_only); - return BLE_ERROR_NONE; -} - ble_error_t nRF5xSecurityManager::get_secure_connections_support( bool &enabled ) { // NRF5x platforms support secure connections - _use_secure_connections = true; + // FIXME: set to true once the ECC library is included + enabled = false; return BLE_ERROR_NONE; } +ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) +{ + _io_capability = io_capability; + return BLE_ERROR_NONE; +} //////////////////////////////////////////////////////////////////////////// // Security settings @@ -130,28 +291,46 @@ ble_error_t nRF5xSecurityManager::get_secure_connections_support( ble_error_t nRF5xSecurityManager::set_authentication_timeout( connection_handle_t connection, uint16_t timeout_in_10ms ) { - // NOTE: Nothing in the Nordic API to manipulate the authentication timeout + // FIXME: Use sd_ble_opt_set(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, ...) when + // available return BLE_ERROR_NOT_IMPLEMENTED; } ble_error_t nRF5xSecurityManager::get_authentication_timeout( connection_handle_t connection, uint16_t &timeout_in_10ms ) { - return BLE_ERROR_NOT_IMPLEMENTED; + // Return default value for now (30s) + timeout_in_10ms = 30 * 100; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size +) { + if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || + (min_encryption_key_size > max_encryption_key_size)) { + return BLE_ERROR_INVALID_PARAM; + } + + _min_encryption_key_size = min_encryption_key_size; + _max_encryption_key_size = max_encryption_key_size; + + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::slave_security_request( connection_handle_t connection, AuthenticationMask authentication ) { - // In the peripheral role, only the bond, mitm, lesc and keypress fields of this structure are used. - + // In the peripheral role, only the bond, mitm, lesc and keypress fields of + // this structure are used. ble_gap_sec_params_t security_params = { /* bond */ authentication.get_bondable(), /* mitm */ authentication.get_mitm(), /* lesc */ authentication.get_secure_connections(), /* keypress */ authentication.get_keypress_notification(), - 0 + /* remainder of the data structure is ignored */ 0 }; uint32_t err = sd_ble_gap_authenticate( @@ -167,22 +346,22 @@ ble_error_t nRF5xSecurityManager::slave_security_request( // ble_error_t nRF5xSecurityManager::enable_encryption( - connection_handle_t connection, - const ltk_t <k, - const rand_t &rand, - const ediv_t &ediv, - bool mitm - ) -{ + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm +) { ble_gap_master_id_t master_id; - ble_gap_enc_info_t enc_info; - memcpy(master_id.rand, rand.data(), rand.size()); - memcpy(&master_id.ediv, ediv.data(), ediv.size()); + memcpy(&master_id.ediv, ediv.data(), ediv.size()); + ble_gap_enc_info_t enc_info; memcpy(enc_info.ltk, ltk.data(), ltk.size()); enc_info.lesc = false; enc_info.auth = mitm; + + // FIXME: how to pass the lenght of the LTK ??? enc_info.ltk_len = ltk.size(); uint32_t err = sd_ble_gap_encrypt( @@ -198,11 +377,10 @@ ble_error_t nRF5xSecurityManager::enable_encryption( connection_handle_t connection, const ltk_t <k, bool mitm -) -{ +) { ble_gap_master_id_t master_id = {0}; - ble_gap_enc_info_t enc_info; + ble_gap_enc_info_t enc_info; memcpy(enc_info.ltk, ltk.data(), ltk.size()); enc_info.lesc = true; enc_info.auth = mitm; @@ -221,7 +399,7 @@ ble_error_t nRF5xSecurityManager::encrypt_data( const byte_array_t<16> &key, encryption_block_t &data ) { - // NO FUNCTION to disable encryption + // FIXME: With signing ? return BLE_ERROR_NOT_IMPLEMENTED; } @@ -232,7 +410,20 @@ ble_error_t nRF5xSecurityManager::encrypt_data( ble_error_t nRF5xSecurityManager::set_private_address_timeout( uint16_t timeout_in_seconds ) { - return BLE_ERROR_NOT_IMPLEMENTED; + // get the previous config + ble_gap_irk_t irk; + ble_opt_t privacy_config; + privacy_config.gap_opt.privacy.p_irk = &irk; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the timeout and return the result + privacy_config.gap_opt.privacy.interval_s = timeout_in_seconds; + err = sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_config); + return convert_sd_error(err); } //////////////////////////////////////////////////////////////////////////// @@ -246,12 +437,12 @@ ble_error_t nRF5xSecurityManager::set_ltk( bool secure_connections ) { ble_gap_enc_info_t enc_info; - memcpy(enc_info.ltk, ltk.data(), ltk.size()); enc_info.lesc = secure_connections; enc_info.auth = mitm; enc_info.ltk_len = ltk.size(); + // FIXME: provide peer irk and csrk ? uint32_t err = sd_ble_gap_sec_info_reply( connection, &enc_info, @@ -277,55 +468,26 @@ ble_error_t nRF5xSecurityManager::set_ltk_not_found( ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) { - // TODO - return BLE_ERROR_NOT_IMPLEMENTED; + // get the previous config + ble_gap_irk_t sd_irk; + ble_opt_t privacy_config; + privacy_config.gap_opt.privacy.p_irk = &sd_irk; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the new irk + memcpy(sd_irk.irk, irk.data(), irk.size()); + err = sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_config); + + return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::set_csrk(const csrk_t& csrk) { - // TODO - return BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xSecurityManager::generate_public_key() -{ - // FIXME - return BLE_ERROR_NOT_IMPLEMENTED; -} - -//////////////////////////////////////////////////////////////////////////// -// Global parameters -// - -ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) -{ - if (passkey) { - _use_default_passkey = true; - _default_passkey = passkey; - } else { - _use_default_passkey = false; - } - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) -{ - _io_capability = io_capability; - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size -) { - if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || - (min_encryption_key_size > max_encryption_key_size)) { - return BLE_ERROR_INVALID_PARAM; - } - - _min_encryption_key_size = min_encryption_key_size; - _max_encryption_key_size = max_encryption_key_size; - + _csrk = csrk; return BLE_ERROR_NONE; } @@ -333,115 +495,11 @@ ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( // Authentication // -ble_error_t nRF5xSecurityManager::send_pairing_request( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist -) { - ble_gap_sec_params_t security_params = { - /* bond */ authentication_requirements.get_bondable(), - /* mitm */ authentication_requirements.get_mitm(), - /* lesc */ authentication_requirements.get_secure_connections(), - /* keypress */ authentication_requirements.get_keypress_notification(), - /* io_caps */ _io_capability.value(), - /* oob */ oob_data_flag, - /* min_key_size */ _min_encryption_key_size, - /* max_key_size */ _max_encryption_key_size, - /* kdist_periph */ { - /* enc */ responder_dist.get_encryption(), - /* id */ responder_dist.get_identity(), - /* sign */ responder_dist.get_signing(), - /* link */ responder_dist.get_link() - }, - /* kdist_central */ { - /* enc */ initiator_dist.get_encryption(), - /* id */ initiator_dist.get_identity(), - /* sign */ initiator_dist.get_signing(), - /* link */ initiator_dist.get_link() - } - }; - - uint32_t err = sd_ble_gap_authenticate( - connection, - &security_params - ); - - return convert_sd_error(err); -} - -ble_error_t nRF5xSecurityManager::send_pairing_response( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist -) { - ble_gap_sec_params_t security_params = { - /* bond */ authentication_requirements.get_bondable(), - /* mitm */ authentication_requirements.get_mitm(), - /* lesc */ authentication_requirements.get_secure_connections(), - /* keypress */ authentication_requirements.get_keypress_notification(), - /* io_caps */ _io_capability.value(), - /* oob */ oob_data_flag, - /* min_key_size */ _min_encryption_key_size, - /* max_key_size */ _max_encryption_key_size, - /* kdist_periph */ { - /* enc */ responder_dist.get_encryption(), - /* id */ responder_dist.get_identity(), - /* sign */ responder_dist.get_signing(), - /* link */ responder_dist.get_link() - }, - /* kdist_central */ { - /* enc */ initiator_dist.get_encryption(), - /* id */ initiator_dist.get_identity(), - /* sign */ initiator_dist.get_signing(), - /* link */ initiator_dist.get_link() - } - }; - - ble_gap_sec_keyset_t keyset = { - /* keys_own */ { - /* encryption key */ &_sp_own_enc_key, - /* id key */ &_sp_own_id_key, - /* signing key */ &_sp_own_sign_key, - /* P-256 Public Key */ &_sp_own_pk - }, - /* keys_peer */ { - /* encryption key */ &_sp_peer_enc_key, - /* id key */ &_sp_peer_id_key, - /* signing key */ &_sp_peer_sign_key, - /* P-256 Public Key */ &_sp_peer_pk - } - }; - - uint32_t err = sd_ble_gap_sec_params_reply( - connection, - /* status */ BLE_GAP_SEC_STATUS_SUCCESS, - /* params */ &security_params, - /* keys ... */ &keyset - ); - - return convert_sd_error(err); -} - -ble_error_t nRF5xSecurityManager::cancel_pairing( - connection_handle_t connection, pairing_failure_t reason -) { - // FIXME: there is no fixed function that can be used to cancel pairing all - // the time. However sd_ble_gap_sec_params_reply should be used to cancel a - // pairing after a pairing request. - - // sd_ble_gap_auth_key_reply should be used to cancel pairing when a key - // entered by the user is required. - - return BLE_ERROR_NOT_IMPLEMENTED; -} - ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) { - uint32_t err = sd_rand_application_vector_get(random_data.buffer(), random_data.size()); + uint32_t err = sd_rand_application_vector_get( + random_data.buffer(), random_data.size() + ); return convert_sd_error(err); } @@ -449,6 +507,16 @@ ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) // MITM // +ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) +{ + PasskeyAscii passkey_ascii(passkey); + ble_opt_t sd_passkey; + sd_passkey.gap_opt.passkey.p_passkey = passkey ? passkey_ascii.value() : NULL; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sd_passkey); + return convert_sd_error(err); +} + + ble_error_t nRF5xSecurityManager::passkey_request_reply( connection_handle_t connection, const passkey_num_t passkey ) { @@ -462,8 +530,8 @@ ble_error_t nRF5xSecurityManager::passkey_request_reply( return convert_sd_error(err); } -ble_error_t nRF5xSecurityManager::legacy_pairing_oob_data_request_reply( - connection_handle_t connection, +ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( + connection_handle_t connection, const oob_tk_t& oob_data ) { uint32_t err = sd_ble_gap_auth_key_reply( @@ -478,49 +546,49 @@ ble_error_t nRF5xSecurityManager::legacy_pairing_oob_data_request_reply( ble_error_t nRF5xSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { - uint32_t err; - - if(confirmation) { - // Accept - err = sd_ble_gap_auth_key_reply( - connection, - BLE_GAP_AUTH_KEY_TYPE_PASSKEY, - NULL - ); - } - else { - // Reject - err = sd_ble_gap_auth_key_reply( - connection, - BLE_GAP_AUTH_KEY_TYPE_NONE, - NULL - ); - } - + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE, + NULL + ); return convert_sd_error(err); } ble_error_t nRF5xSecurityManager::send_keypress_notification( connection_handle_t connection, Keypress_t keypress ) { - uint8_t kp_not = static_cast(keypress); - uint32_t err = sd_ble_gap_keypress_notify( connection, - kp_not + static_cast(keypress) ); - return convert_sd_error(err); } -ble_error_t nRF5xSecurityManager::oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + +ble_error_t nRF5xSecurityManager::generate_secure_connections_oob( + connection_handle_t connection ) { + // FIXME: made with external library; requires SDK v13 return BLE_ERROR_NOT_IMPLEMENTED; } + +ble_error_t nRF5xSecurityManager::secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm +) { + // FIXME: store locally + return BLE_ERROR_NOT_IMPLEMENTED; +} + +bool nRF5xSecurityManager::is_secure_connections_oob_present( + const address_t &address +) { + // FIXME: lookup local store + return false; +} + nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() { static nRF5xSecurityManager _security_manager; @@ -529,9 +597,8 @@ nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) { - SecurityManager::EventHandler* handler = - get_security_manager().get_event_handler(); - nRF5xSecurityManager* inst = &nRF5xSecurityManager::get_security_manager(); + nRF5xSecurityManager& self = nRF5xSecurityManager::get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); if ((evt == NULL) || (handler == NULL)) { return false; @@ -539,19 +606,13 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) const ble_gap_evt_t& gap_evt = evt->evt.gap_evt; uint16_t connection = gap_evt.conn_handle; + pairing_control_block_t* pairing_cb = self.get_pairing_cb(connection); switch (evt->header.evt_id) { case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { const ble_gap_sec_params_t& params = gap_evt.params.sec_params_request.peer_params; - AuthenticationMask authentication_requirements( - params.bond, - params.mitm, - params.lesc, - params.keypress - ); - KeyDistribution initiator_dist( params.kdist_peer.enc, params.kdist_peer.id, @@ -566,14 +627,48 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) params.kdist_own.link ); - // FIXME: pass min key size - handler->on_pairing_request( - connection, - params.oob, - authentication_requirements, - initiator_dist, - responder_dist - ); + if (pairing_cb && pairing_cb->role == PAIRING_INITIATOR) { + // when this event is received by an initiator, it should not be + // forwarded via the handler; this is not a behaviour expected + // by the bluetooth standard ... + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ NULL, + /* keys ... */ &keyset + ); + + // in case of error; release the pairing control block and signal + // it to the event handler + if (err) { + release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + pairing_failure_t::UNSPECIFIED_REASON + ); + } + } else { + AuthenticationMask authentication_requirements( + params.bond, + params.mitm, + params.lesc, + params.keypress + ); + + + handler->on_pairing_request( + connection, + params.oob, + authentication_requirements, + initiator_dist, + responder_dist + ); + } return true; } @@ -600,17 +695,16 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) PasskeyAscii::to_num(req.passkey) ); } else { - // handle this case for secure pairing + // FIXME handle this case for secure pairing } return true; } case BLE_GAP_EVT_KEY_PRESSED: { - const ble_gap_evt_key_pressed_t& notf = gap_evt.params.key_pressed; handler->on_keypress_notification( connection, - (Keypress_t)notf.kp_not + (Keypress_t)gap_evt.params.key_pressed.kp_not ); return true; } @@ -634,42 +728,95 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) } case BLE_GAP_EVT_LESC_DHKEY_REQUEST: - // TODO: Add with LESC support + // FIXME: Add with LESC support return true; case BLE_GAP_EVT_AUTH_STATUS: { - const ble_gap_evt_auth_status_t& status = - gap_evt.params.auth_status; + const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status; switch (status.auth_status) { - case BLE_GAP_SEC_STATUS_SUCCESS: - // Keys stored (_sp*) are valid - handler->on_keys_distributed_local_ltk( - connection, - ltk_t(inst->_sp_own_enc_key.enc_info.ltk) - ); + // NOTE: pairing_cb must be valid if this event has been + // received as it is being allocated earlier and release + // in this block + // The memory is released before the last call to the event handler + // to free the heap a bit before subsequent allocation with user + // code. + case BLE_GAP_SEC_STATUS_SUCCESS: { + KeyDistribution own_dist; + KeyDistribution peer_dist; - handler->on_keys_distributed_local_ediv_rand( - connection, - ediv_t(reinterpret_cast(&inst->_sp_own_enc_key.master_id.ediv)), - inst->_sp_own_enc_key.master_id.rand - ); + if (pairing_cb->role == PAIRING_INITIATOR) { + own_dist = pairing_cb->initiator_dist; + peer_dist = pairing_cb->responder_dist; + } else { + own_dist = pairing_cb->responder_dist; + peer_dist = pairing_cb->initiator_dist; + } - handler->on_keys_distributed_ltk( - connection, - ltk_t(inst->_sp_peer_enc_key.enc_info.ltk) - ); + if (own_dist.get_encryption()) { + handler->on_keys_distributed_local_ltk( + connection, + ltk_t(pairing_cb->own_enc_key.enc_info.ltk) + ); - handler->on_keys_distributed_ediv_rand( - connection, - ediv_t(reinterpret_cast(&inst->_sp_peer_enc_key.master_id.ediv)), - inst->_sp_peer_enc_key.master_id.rand - ); + handler->on_keys_distributed_local_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->own_enc_key.master_id.ediv + )), + pairing_cb->own_enc_key.master_id.rand + ); + } + + if (peer_dist.get_encryption()) { + handler->on_keys_distributed_ltk( + connection, + ltk_t(pairing_cb->peer_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->peer_enc_key.master_id.ediv + )), + pairing_cb->peer_enc_key.master_id.rand + ); + } + + if (peer_dist.get_identity()) { + handler->on_keys_distributed_irk( + connection, + irk_t(pairing_cb->peer_id_key.id_info.irk) + ); + + advertising_peer_address_type_t + address_type(advertising_peer_address_type_t::PUBLIC_ADDRESS); + + if (pairing_cb->peer_id_key.id_addr_info.addr_type) { + address_type = advertising_peer_address_type_t::RANDOM_ADDRESS; + } + + handler->on_keys_distributed_bdaddr( + connection, + address_type, + ble::address_t(pairing_cb->peer_id_key.id_addr_info.addr) + ); + } + + if (peer_dist.get_signing()) { + handler->on_keys_distributed_csrk( + connection, + pairing_cb->peer_sign_key.csrk + ); + } + + self.release_pairing_cb(pairing_cb); + handler->on_pairing_completed(connection); break; - - // TODO add signing & privacy keys here + } case BLE_GAP_SEC_STATUS_TIMEOUT: + self.release_pairing_cb(pairing_cb); handler->on_pairing_timed_out(connection); break; @@ -687,6 +834,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) case BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE: case BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG: case BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED: + self.release_pairing_cb(pairing_cb); handler->on_pairing_error( connection, (pairing_failure_t::type) (status.auth_status & 0xF) @@ -694,47 +842,180 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) break; default: + self.release_pairing_cb(pairing_cb); break; } - return true; } - case BLE_GAP_EVT_CONN_SEC_UPDATE: - { - const ble_gap_evt_conn_sec_update_t& req = + case BLE_GAP_EVT_CONN_SEC_UPDATE: { + const ble_gap_evt_conn_sec_update_t& req = gap_evt.params.conn_sec_update; - if( (req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2) ) - { - handler->on_link_encryption_result(connection, link_encryption_t::ENCRYPTED); - } - else - { - handler->on_link_encryption_result(connection, link_encryption_t::NOT_ENCRYPTED); - } - return true; - } - case BLE_GAP_EVT_TIMEOUT: - // FIXME: forward event when available - return true; - case BLE_GAP_EVT_SEC_REQUEST: - { - const ble_gap_evt_sec_request_t& req = - gap_evt.params.sec_request; - AuthenticationMask auth_mask(req.bond, req.mitm, req.lesc, req.keypress); - handler->on_slave_security_request( - connection, - auth_mask - ); + if((req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2)) { + handler->on_link_encryption_result( + connection, link_encryption_t::ENCRYPTED + ); + } else { + handler->on_link_encryption_result( + connection, link_encryption_t::NOT_ENCRYPTED + ); + } return true; } + + case BLE_GAP_EVT_TIMEOUT: { + switch (gap_evt.params.timeout.src) { + case BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST: + // Note: pairing_cb does not exist at this point; it is + // created when the module receive the pairing request. + handler->on_link_encryption_request_timed_out(connection); + return true; + + // FIXME: enable with latest SDK +#if 0 + case BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD: + handler->on_valid_mic_timeout(connection); + return true; +#endif + default: + return false; + } + return false; + } + + case BLE_GAP_EVT_SEC_REQUEST: { + const ble_gap_evt_sec_request_t& req = gap_evt.params.sec_request; + handler->on_slave_security_request( + connection, + AuthenticationMask(req.bond, req.mitm, req.lesc, req.keypress) + ); + return true; + } + default: return false; } } +ble_gap_sec_params_t nRF5xSecurityManager::make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + ble_gap_sec_params_t security_params = { + /* bond */ authentication_requirements.get_bondable(), + /* mitm */ authentication_requirements.get_mitm(), + /* lesc */ authentication_requirements.get_secure_connections(), + /* keypress */ authentication_requirements.get_keypress_notification(), + /* io_caps */ _io_capability.value(), + /* oob */ oob_data_flag, + /* min_key_size */ _min_encryption_key_size, + /* max_key_size */ _max_encryption_key_size, + /* kdist_periph */ { + /* enc */ responder_dist.get_encryption(), + /* id */ responder_dist.get_identity(), + /* sign */ responder_dist.get_signing(), + /* link */ responder_dist.get_link() + }, + /* kdist_central */ { + /* enc */ initiator_dist.get_encryption(), + /* id */ initiator_dist.get_identity(), + /* sign */ initiator_dist.get_signing(), + /* link */ initiator_dist.get_link() + } + }; + return security_params; +} + +ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_cb.initiator_dist = initiator_dist; + pairing_cb.responder_dist = responder_dist; + + KeyDistribution* own_dist = NULL; + KeyDistribution* peer_dist = NULL; + + if (pairing_cb.role == PAIRING_INITIATOR) { + own_dist = &initiator_dist; + peer_dist = &responder_dist; + } else { + own_dist = &responder_dist; + peer_dist = &initiator_dist; + } + + ble_gap_sec_keyset_t keyset = { + /* keys_own */ { + own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL, + own_dist->get_identity() ? &pairing_cb.own_id_key : NULL, + own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL, + own_dist->get_link() ? &pairing_cb.own_pk : NULL + }, + /* keys_peer */ { + peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL, + peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL, + peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL, + peer_dist->get_link() ? &pairing_cb.peer_pk : NULL + } + }; + + // copy csrk if necessary + if (keyset.keys_own.p_sign_key) { + memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size()); + } + + return keyset; +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::allocate_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pairing_cb = + new (std::nothrow) pairing_control_block_t(); + if (pairing_cb) { + pairing_cb->next = _control_blocks; + _control_blocks = pairing_cb; + } + return pairing_cb; +} + +void nRF5xSecurityManager::release_pairing_cb(pairing_control_block_t* pairing_cb) +{ + if (pairing_cb == _control_blocks) { + _control_blocks = _control_blocks->next; + delete pairing_cb; + } else { + pairing_control_block_t* it = _control_blocks; + while (it->next) { + if (it->next == pairing_cb) { + it->next = pairing_cb->next; + delete pairing_cb; + return; + } + it = it->next; + } + } +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pcb = _control_blocks; + while (pcb) { + if (pcb->connection == connection) { + return pcb; + } + pcb = pcb->next; + } + + return NULL; +} + } // nordic } // vendor } // pal diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 1cc4a1126d..add7d4e6ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -83,16 +83,43 @@ public: virtual ble_error_t clear_resolving_list(); //////////////////////////////////////////////////////////////////////////// - // Feature support + // Pairing // /** - * @see ::ble::pal::SecurityManager::set_secure_connections_support + * @see ::ble::pal::SecurityManager::send_pairing_request */ - virtual ble_error_t set_secure_connections_support( - bool enabled, bool secure_connections_only = false + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist ); + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + /** * @see ::ble::pal::SecurityManager::get_secure_connections_support */ @@ -100,6 +127,11 @@ public: bool &enabled ); + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + //////////////////////////////////////////////////////////////////////////// // Security settings // @@ -118,6 +150,17 @@ public: connection_handle_t, uint16_t &timeout_in_10ms ); + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ virtual ble_error_t slave_security_request( connection_handle_t connection, AuthenticationMask authentication @@ -195,66 +238,10 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); - /** - * @see ::ble::pal::SecurityManager::generate_public_key - */ - virtual ble_error_t generate_public_key(); - - //////////////////////////////////////////////////////////////////////////// - // Global parameters - // - - /** - * @see ::ble::pal::SecurityManager::set_display_passkey - */ - virtual ble_error_t set_display_passkey(passkey_num_t passkey); - - /** - * @see ::ble::pal::SecurityManager::set_io_capability - */ - virtual ble_error_t set_io_capability(io_capability_t io_capability); - - /** - * @see ::ble::pal::SecurityManager::set_encryption_key_requirements - */ - virtual ble_error_t set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size - ); - //////////////////////////////////////////////////////////////////////////// // Authentication // - /** - * @see ::ble::pal::SecurityManager::send_pairing_request - */ - virtual ble_error_t send_pairing_request( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::send_pairing_response - */ - virtual ble_error_t send_pairing_response( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::cancel_pairing - */ - virtual ble_error_t cancel_pairing( - connection_handle_t connection, pairing_failure_t reason - ); - /** * @see ::ble::pal::SecurityManager::get_random_data */ @@ -264,6 +251,11 @@ public: // MITM // + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + /** * @see ::ble::pal::SecurityManager::passkey_request_reply */ @@ -273,9 +265,9 @@ public: ); /** - * @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply */ - virtual ble_error_t legacy_pairing_oob_data_request_reply( + virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t &oob_data ); @@ -295,12 +287,26 @@ public: ); /** - * @see ::ble::pal::SecurityManager::oob_data_verified + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t oob_data_verified( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random + virtual ble_error_t generate_secure_connections_oob( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_received + */ + virtual ble_error_t secure_connections_oob_received( + const address_t &address, + const oob_lesc_value_t &random, + const oob_confirm_t &confirm + ); + + /** + * @see ::ble::pal::SecurityManager::is_secure_connections_oob_present + */ + virtual bool is_secure_connections_oob_present( + const address_t &address ); // singleton of nordic Security Manager @@ -310,28 +316,31 @@ public: bool sm_handler(const ble_evt_t *evt); private: - bool _use_legacy_pairing; - bool _use_secure_connections; - bool _use_default_passkey; - passkey_num_t _default_passkey; - - irk_t _irk; csrk_t _csrk; - io_capability_t _io_capability; uint8_t _min_encryption_key_size; uint8_t _max_encryption_key_size; - // The softdevice requires us to manage memory for these keys - ble_gap_enc_key_t _sp_own_enc_key; - ble_gap_id_key_t _sp_own_id_key; - ble_gap_sign_info_t _sp_own_sign_key; - ble_gap_lesc_p256_pk_t _sp_own_pk; + struct pairing_control_block_t; - ble_gap_enc_key_t _sp_peer_enc_key; - ble_gap_id_key_t _sp_peer_id_key; - ble_gap_sign_info_t _sp_peer_sign_key; - ble_gap_lesc_p256_pk_t _sp_peer_pk; + ble_gap_sec_params_t make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + ble_gap_sec_keyset_t make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection); + void release_pairing_cb(pairing_control_block_t* pairing_cb); + pairing_control_block_t* get_pairing_cb(connection_handle_t connection); + + pairing_control_block_t* _control_blocks; }; } // nordic From 66867d4dd32e0b123c5acf480a8b8984f410c5db Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 16 Mar 2018 14:48:04 +0000 Subject: [PATCH 018/274] oob stored in generic and handed over to pal when requested --- .../ble/generic/GenericSecurityManager.h | 14 ++++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 60 ++++++++++--------- .../source/generic/GenericSecurityManager.cpp | 31 ++++++++-- .../TARGET_CORDIO/CordioPalSecurityManager.h | 18 ++---- .../source/CordioPalSecurityManager.cpp | 15 ++--- 5 files changed, 82 insertions(+), 56 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 322cef4b5d..8b33c08dae 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -439,6 +439,12 @@ private: pal::SecurityDb &_db; pal::ConnectionEventMonitor &_connection_monitor; + /* OOB data */ + address_t _oob_peer_address; + oob_lesc_value_t _oob_peer_random; + oob_confirm_t _oob_peer_confirm; + oob_lesc_value_t _oob_local_random; + pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; @@ -548,6 +554,12 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_request + */ + virtual void on_secure_connections_oob_request( + connection_handle_t connection + ); + /** @copydoc ble::pal::SecurityManager::on_legacy_pairing_oob_request */ virtual void on_legacy_pairing_oob_request( @@ -557,7 +569,7 @@ public: /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated */ virtual void on_secure_connections_oob_generated( - const address_t &local_address, + connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ); diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index ac984ab0d8..e452f6fe4c 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -367,6 +367,17 @@ public: Keypress_t keypress ) = 0; + /** + * Request OOB data from the user application. + * + * @param[in] connection connection handle + * @note shall be followed by: pal::SecurityManager::secure_connections_oob_request_reply + * or a cancellation of the procedure. + */ + virtual void on_secure_connections_oob_request( + connection_handle_t connection + ) = 0; + /** * Request OOB data from the user application. * @@ -381,14 +392,14 @@ public: /** * Send OOB data to the application for transport to the peer. * - * @param[in] address address of the local device + * @param[in] connection connection handle * @param[in] random random number used to generate the confirmation * @param[in] confirm confirmation value to be use for authentication * in secure connections pairing * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ virtual void on_secure_connections_oob_generated( - const address_t &local_address, + connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ) = 0; @@ -909,7 +920,24 @@ public: ) = 0; /** - * Reply to an oob data request received from the SecurityManagerEventHandler. + * Reply to a Secure Connections oob data request received from the SecurityManagerEventHandler. + * + * @param[in] connection connection handle + * @param[in] local_random local random number used for the last oob exchange + * @param[in] peer_random random number used to generate the confirmation on peer + * @param[in] peer_confirm confirmation value to be use for authentication + * in secure connections pairing + * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ) = 0; + + /** + * Reply to a legacy pairing oob data request received from the SecurityManagerEventHandler. * * @param[in] connection connection handle * @param[in] oob_data pointer to out of band data @@ -955,32 +983,6 @@ public: connection_handle_t connection ) = 0; - /** - * Supply the stack with the OOB data for secure connections. - * - * @param[in] address address of the peer device this data comes from - * @param[in] random random number used to generate the confirmation - * @param[in] confirm confirmation value to be use for authentication - * in secure connections pairing - * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. - */ - virtual ble_error_t secure_connections_oob_received( - const address_t &address, - const oob_lesc_value_t &random, - const oob_confirm_t &confirm - ) = 0; - - /** - * Supply the stack with the OOB data for secure connections. - * - * @param[in] address address of the peer device oob data is needed for - * @return True if oob data present, false if not or if the functionality - * is not implemented. - */ - virtual bool is_secure_connections_oob_present( - const address_t &address - ) = 0; - /* Entry points for the underlying stack to report events back to the user. */ public: /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 0e6cb57e5e..95b15269b1 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -563,7 +563,10 @@ ble_error_t GenericSecurityManager::oobReceived( const oob_confirm_t *confirm ) { if (address && random && confirm) { - return _pal.secure_connections_oob_received(*address, *random, *confirm); + _oob_peer_address = *address; + _oob_peer_random = *random; + _oob_peer_confirm = *confirm; + return BLE_ERROR_NONE; } return BLE_ERROR_INVALID_PARAM; @@ -696,7 +699,7 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) cb->oob_present = cb->attempt_oob; if (_default_authentication.get_secure_connections()) { - cb->oob_present = _pal.is_secure_connections_oob_present(cb->peer_address); + cb->oob_present = (cb->peer_address == _oob_peer_address); } } @@ -944,17 +947,37 @@ void GenericSecurityManager::on_confirmation_request(connection_handle_t connect eventHandler->confirmationRequest(connection); } +void GenericSecurityManager::on_secure_connections_oob_request(connection_handle_t connection) { + set_mitm_performed(connection); + + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + + if (cb->peer_address == _oob_peer_address) { + _pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm); + } else { + _pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE); + } +} + void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { set_mitm_performed(connection); eventHandler->legacyPairingOobRequest(connection); } void GenericSecurityManager::on_secure_connections_oob_generated( - const address_t &local_address, + connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ) { - eventHandler->oobGenerated(&local_address, &random, &confirm); + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + eventHandler->oobGenerated(&cb->local_address, &random, &confirm); + _oob_local_random = random; } //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index d79c1c788c..1181abb273 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -302,19 +302,13 @@ public: ); /** - * @see ::ble::pal::SecurityManager::secure_connections_oob_received + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply */ - virtual ble_error_t secure_connections_oob_received( - const address_t &address, - const oob_lesc_value_t &random, - const oob_confirm_t &confirm - ); - - /** - * @see ::ble::pal::SecurityManager::is_secure_connections_oob_present - */ - virtual bool is_secure_connections_oob_present( - const address_t &address + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm ); // singleton of the ARM Cordio Security Manager diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 24e405ef65..7764bbd09c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -400,20 +400,15 @@ ble_error_t CordioSecurityManager::generate_secure_connections_oob( return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t CordioSecurityManager::secure_connections_oob_received( - const address_t &address, - const oob_lesc_value_t &random, - const oob_confirm_t &confirm +ble_error_t CordioSecurityManager::secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm ) { return BLE_ERROR_NOT_IMPLEMENTED; } -bool CordioSecurityManager::is_secure_connections_oob_present( - const address_t &address -) { - return false; -} - CordioSecurityManager& CordioSecurityManager::get_security_manager() { static CordioSecurityManager _security_manager; From 909f9513cfd594dfceabdf1eadf4962533900425 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 12:01:34 +0000 Subject: [PATCH 019/274] allow preloading legacy oob, generate tk --- .../ble/generic/GenericSecurityManager.h | 3 ++ .../source/generic/GenericSecurityManager.cpp | 33 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 8b33c08dae..583097fa76 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -433,6 +433,7 @@ private: uint8_t attempt_oob:1; uint8_t oob_mitm_protection:1; uint8_t oob_present:1; + uint8_t legacy_pairing_oob_request_pending:1; }; pal::SecurityManager &_pal; @@ -444,6 +445,8 @@ private: oob_lesc_value_t _oob_peer_random; oob_confirm_t _oob_peer_confirm; oob_lesc_value_t _oob_local_random; + address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */ + oob_tk_t _oob_temporary_key; /**< used for legacy pairing */ pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 95b15269b1..3994319709 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -513,6 +513,14 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; + _oob_temporary_key_creator_address = cb->local_address; + get_random_data(_oob_temporary_key.buffer(), 16); + + eventHandler->legacyPairingOobGenerated( + &_oob_temporary_key_creator_address, + &_oob_temporary_key + ); + _pal.generate_secure_connections_oob(connection); return BLE_ERROR_NONE; @@ -552,7 +560,13 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( return BLE_ERROR_INVALID_PARAM; } - return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk); + _oob_temporary_key = *tk; + _oob_peer_address = *address; + + if (cb->legacy_pairing_oob_request_pending) { + cb->legacy_pairing_oob_request_pending = false; + return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk); + } } return BLE_ERROR_NONE; } @@ -964,7 +978,19 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { set_mitm_performed(connection); - eventHandler->legacyPairingOobRequest(connection); + + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + + if (cb->peer_address == _oob_temporary_key_creator_address + || cb->local_address == _oob_temporary_key_creator_address) { + _pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key); + } else { + cb->legacy_pairing_oob_request_pending = true; + eventHandler->legacyPairingOobRequest(connection); + } } void GenericSecurityManager::on_secure_connections_oob_generated( @@ -1135,7 +1161,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : mitm_performed(false), attempt_oob(false), oob_mitm_protection(false), - oob_present(false) { } + oob_present(false), + legacy_pairing_oob_request_pending(false) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { From c848c79a5bc856fb0387e7e2a4f730da28ffd311 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 12:10:21 +0000 Subject: [PATCH 020/274] avoid code redundancy --- .../source/generic/GenericSecurityManager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 3994319709..ede91d5db1 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -561,11 +561,10 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( } _oob_temporary_key = *tk; - _oob_peer_address = *address; + _oob_temporary_key_creator_address = *address; if (cb->legacy_pairing_oob_request_pending) { - cb->legacy_pairing_oob_request_pending = false; - return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk); + on_legacy_pairing_oob_request(cb->connection); } } return BLE_ERROR_NONE; @@ -977,8 +976,6 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle } void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) { - set_mitm_performed(connection); - ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -986,10 +983,15 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c if (cb->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); - } else { + + } else if (!cb->legacy_pairing_oob_request_pending) { + cb->legacy_pairing_oob_request_pending = true; eventHandler->legacyPairingOobRequest(connection); + } } From 2b2d9a24534f6f03d8502dcf7ba01d2ce1960e56 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 12:23:37 +0000 Subject: [PATCH 021/274] reset pending state when attempt ends, added comments --- .../source/generic/GenericSecurityManager.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index ede91d5db1..afb7fc7469 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -565,6 +565,10 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( if (cb->legacy_pairing_oob_request_pending) { on_legacy_pairing_oob_request(cb->connection); + /* legacy_pairing_oob_request_pending stops us from + * going into a loop of asking the user for oob + * so this reset needs to happen after the call above */ + cb->legacy_pairing_oob_request_pending = false; } } return BLE_ERROR_NONE; @@ -720,6 +724,11 @@ void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, ControlBlock_t *cb = get_control_block(connection); if (cb) { cb->mitm_performed = enable; + /* whenever we reset mitm performed we also reset pending requests + * as this happens whenever a new pairing attempt happens */ + if (!enable) { + cb->legacy_pairing_oob_request_pending = false; + } } } From 350924129f0146353b94f20ce2af46604e6acd26 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 12:32:01 +0000 Subject: [PATCH 022/274] fix the attempt oob flag if we receive oob --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index afb7fc7469..cef46986a8 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -563,6 +563,10 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( _oob_temporary_key = *tk; _oob_temporary_key_creator_address = *address; + if (cb->peer_address == _oob_temporary_key_creator_address) { + cb->attempt_oob = true; + } + if (cb->legacy_pairing_oob_request_pending) { on_legacy_pairing_oob_request(cb->connection); /* legacy_pairing_oob_request_pending stops us from From 81cb1f9c83c9eafdd3ff927542652cdba56adc82 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 17:11:15 +0000 Subject: [PATCH 023/274] enable encryption for slave request added --- .../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 95b15269b1..e773190e4c 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -853,16 +853,23 @@ void GenericSecurityManager::on_slave_security_request( return; } - if (authentication.get_secure_connections() - && _default_authentication.get_secure_connections() - && !cb->secure_connections_paired) { - requestPairing(connection); + bool pairing_required = false; + + if (authentication.get_secure_connections() && !cb->secure_connections_paired + && _default_authentication.get_secure_connections()) { + pairing_required = true; } - if (authentication.get_mitm() - && !cb->ltk_mitm_protected) { + if (authentication.get_mitm() && !cb->ltk_mitm_protected) { + pairing_required = true; cb->mitm_requested = true; + } + + if (pairing_required) { requestPairing(connection); + } else { + /* this will refresh keys if encryption is already present */ + enable_encryption(connection); } } From 6833c79fb301ab3bdab22b555c1fb56d54ff5a69 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 22 Mar 2018 17:54:13 +0000 Subject: [PATCH 024/274] don't request encrypt when pending --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index e773190e4c..69f0306e5e 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -867,7 +867,7 @@ void GenericSecurityManager::on_slave_security_request( if (pairing_required) { requestPairing(connection); - } else { + } else if (!cb->encryption_requested) { /* this will refresh keys if encryption is already present */ enable_encryption(connection); } From e25d5c9aa301e9538e4cf7dc4fd7c4bf2ac1b103 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 17:56:59 +0000 Subject: [PATCH 025/274] BLE: qualification of SecurityManager types --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index e452f6fe4c..5dca19404b 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -27,10 +27,10 @@ namespace ble { namespace pal { -typedef SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; -typedef SecurityManager::SecurityMode_t SecurityMode_t; -typedef SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; -typedef SecurityManager::Keypress_t Keypress_t; +typedef ::SecurityManager::SecurityCompletionStatus_t SecurityCompletionStatus_t; +typedef ::SecurityManager::SecurityMode_t SecurityMode_t; +typedef ::SecurityManager::LinkSecurityStatus_t LinkSecurityStatus_t; +typedef ::SecurityManager::Keypress_t Keypress_t; /** * Key distribution as required by the SMP with convenient setters and getters, From 0a710e533192f4dd9301f4d6c4babe149e3faf7a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:04:47 +0000 Subject: [PATCH 026/274] BLE: Initialize the pal in GenericSecurityManager --- .gitignore | 2 ++ .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 88ff051ecc..7b85cc3417 100644 --- a/.gitignore +++ b/.gitignore @@ -86,3 +86,5 @@ tags # Visual Studio Code .vscode/ + +features/FEATURE_BLE/targets/TARGET_CORDIO/stack_backup/ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 7c210cc17a..2acca2755f 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -39,6 +39,11 @@ ble_error_t GenericSecurityManager::init( const Passkey_t passkey, bool signing ) { + ble_error_t err = _pal.initialize(); + if (err) { + return err; + } + _db.restore(); _pal.set_io_capability((io_capability_t::type) iocaps); @@ -73,6 +78,7 @@ ble_error_t GenericSecurityManager::init( ble_error_t GenericSecurityManager::reset(void) { _db.sync(); + _pal.reset(); SecurityManager::reset(); return BLE_ERROR_NONE; From b859907481f0b7592badc46950bb8b8e48f52996 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:05:31 +0000 Subject: [PATCH 027/274] Cordio: remove generate_public_key from the security manager. --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 1181abb273..d8fb104990 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -195,11 +195,6 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); - /** - * @see ::ble::pal::SecurityManager::generate_public_key - */ - virtual ble_error_t generate_public_key(); - //////////////////////////////////////////////////////////////////////////// // Global parameters // From 98efb9da068e9d627469047cdd6301641a5ddf2d Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 23 Mar 2018 18:31:27 +0000 Subject: [PATCH 028/274] generate oob at will and without passing in connection handle --- features/FEATURE_BLE/ble/SecurityManager.h | 16 ++++++- .../ble/generic/GenericSecurityManager.h | 6 ++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 9 +--- .../source/generic/GenericSecurityManager.cpp | 46 ++++++++++++++----- .../TARGET_CORDIO/CordioPalSecurityManager.h | 4 +- .../source/CordioPalSecurityManager.cpp | 4 +- 6 files changed, 58 insertions(+), 27 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 43a83e7fe7..9bf6ea26bc 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -735,9 +735,23 @@ public: // MITM // + /** + * Generate OOB data with the given address. If Secure Connections is supported this will + * also generate Secure Connections OOB data on top of legacy pairing OOB data. This can be used + * to generate such data before any connections take place. + * + * @param[in] address The local address you will use in the connection using this OOB data. + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + virtual ble_error_t generateOOB(const ble::address_t *address) { + /* Avoid compiler warnings about unused variables */ + (void) address; + return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ + } + /** * Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will - * generate Secure Connections OOB data through oobGenerated(). + * generate Secure Connections OOB data through oobGenerated() on top of legacy pairing OOB data. * * @param[in] connectionHandle Handle to identify the connection. * @param[in] useOOB If set to true, authenticate using OOB data. diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 583097fa76..b01020b19e 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -192,6 +192,10 @@ public: // MITM // + virtual ble_error_t generateOOB( + const address_t *address + ); + virtual ble_error_t setOOBDataUsage( connection_handle_t connection, bool useOOB, @@ -441,6 +445,7 @@ private: pal::ConnectionEventMonitor &_connection_monitor; /* OOB data */ + address_t _oob_local_address; address_t _oob_peer_address; oob_lesc_value_t _oob_peer_random; oob_confirm_t _oob_peer_confirm; @@ -572,7 +577,6 @@ public: /** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated */ virtual void on_secure_connections_oob_generated( - connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ); diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index e452f6fe4c..d8b0dcf986 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -399,7 +399,6 @@ public: * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ virtual void on_secure_connections_oob_generated( - connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ) = 0; @@ -975,13 +974,9 @@ public: ) = 0; /** - * Generate local OOB data to be sent to the application which sends it to the peer. - * - * @param[in] connectionHandle Handle to identify the connection. + * Generate local OOB data to be sent to the application which sends it to the peer.p */ - virtual ble_error_t generate_secure_connections_oob( - connection_handle_t connection - ) = 0; + virtual ble_error_t generate_secure_connections_oob() = 0; /* Entry points for the underlying stack to report events back to the user. */ public: diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 7c210cc17a..dcb83331f7 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -500,6 +500,25 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co // MITM // +ble_error_t GenericSecurityManager::generateOOB( + const address_t *address +) { + /* legacy pairing */ + _oob_temporary_key_creator_address = *address; + get_random_data(_oob_temporary_key.buffer(), 16); + + eventHandler->legacyPairingOobGenerated( + &_oob_temporary_key_creator_address, + &_oob_temporary_key + ); + + /* secure connections */ + _oob_local_address = *address; + _pal.generate_secure_connections_oob(); + + return BLE_ERROR_NONE; +} + ble_error_t GenericSecurityManager::setOOBDataUsage( connection_handle_t connection, bool useOOB, @@ -513,6 +532,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; + /* legacy pairing */ _oob_temporary_key_creator_address = cb->local_address; get_random_data(_oob_temporary_key.buffer(), 16); @@ -521,7 +541,9 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( &_oob_temporary_key ); - _pal.generate_secure_connections_oob(connection); + /* secure connections */ + _oob_local_address = cb->local_address; + _pal.generate_secure_connections_oob(); return BLE_ERROR_NONE; } @@ -714,13 +736,18 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection) return; } - /* only update the oob state if we support secure connections, - * otherwise follow the user set preference for providing legacy - * pairing oob data */ - cb->oob_present = cb->attempt_oob; - + /* 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); + } 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 + || cb->local_address == _oob_temporary_key_creator_address) { + cb->oob_present = true; + } } } @@ -1016,15 +1043,10 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c } void GenericSecurityManager::on_secure_connections_oob_generated( - connection_handle_t connection, const oob_lesc_value_t &random, const oob_confirm_t &confirm ) { - ControlBlock_t *cb = get_control_block(connection); - if (!cb) { - return; - } - eventHandler->oobGenerated(&cb->local_address, &random, &confirm); + eventHandler->oobGenerated(&_oob_local_address, &random, &confirm); _oob_local_random = random; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 1181abb273..0461beaec6 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -297,9 +297,7 @@ public: /** * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t generate_secure_connections_oob( - connection_handle_t connection - ); + virtual ble_error_t generate_secure_connections_oob(); /** * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 7764bbd09c..1948c0560e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -394,9 +394,7 @@ ble_error_t CordioSecurityManager::send_keypress_notification( return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::generate_secure_connections_oob( - connection_handle_t connection -) { +ble_error_t CordioSecurityManager::generate_secure_connections_oob() { return BLE_ERROR_NOT_IMPLEMENTED; } From 3579653533e8a3d89255323b6edf45fd2712e77c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 9 Mar 2018 18:06:22 +0000 Subject: [PATCH 029/274] Cordio: Implement missing functions for secure connection --- .../TARGET_CORDIO/CordioPalSecurityManager.h | 130 +++++++++--------- .../source/CordioPalSecurityManager.cpp | 86 +++++++++--- 2 files changed, 135 insertions(+), 81 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index d8fb104990..458f20311c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -20,6 +20,8 @@ #include "ble/pal/PalSecurityManager.h" #include "wsf_types.h" #include "wsf_os.h" +#include "sec_api.h" +#include "smp_defs.h" namespace ble { namespace pal { @@ -83,16 +85,42 @@ public: virtual ble_error_t clear_resolving_list(); //////////////////////////////////////////////////////////////////////////// - // Feature support + // Pairing // /** - * @see ::ble::pal::SecurityManager::set_secure_connections_support + * @see ::ble::pal::SecurityManager::send_pairing_request */ - virtual ble_error_t set_secure_connections_support( - bool enabled, bool secure_connections_only = false + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist ); + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + /** * @see ::ble::pal::SecurityManager::get_secure_connections_support */ @@ -100,6 +128,11 @@ public: bool &enabled ); + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + //////////////////////////////////////////////////////////////////////////// // Security settings // @@ -118,6 +151,17 @@ public: connection_handle_t, uint16_t &timeout_in_10ms ); + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ virtual ble_error_t slave_security_request( connection_handle_t connection, AuthenticationMask authentication @@ -195,61 +239,10 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); - //////////////////////////////////////////////////////////////////////////// - // Global parameters - // - - /** - * @see ::ble::pal::SecurityManager::set_display_passkey - */ - virtual ble_error_t set_display_passkey(passkey_num_t passkey); - - /** - * @see ::ble::pal::SecurityManager::set_io_capability - */ - virtual ble_error_t set_io_capability(io_capability_t io_capability); - - /** - * @see ::ble::pal::SecurityManager::set_encryption_key_requirements - */ - virtual ble_error_t set_encryption_key_requirements( - uint8_t min_encryption_key_size, - uint8_t max_encryption_key_size - ); - //////////////////////////////////////////////////////////////////////////// // Authentication // - /** - * @see ::ble::pal::SecurityManager::send_pairing_request - */ - virtual ble_error_t send_pairing_request( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::send_pairing_response - */ - virtual ble_error_t send_pairing_response( - connection_handle_t connection, - bool oob_data_flag, - AuthenticationMask authentication_requirements, - KeyDistribution initiator_dist, - KeyDistribution responder_dist - ); - - /** - * @see ::ble::pal::SecurityManager::cancel_pairing - */ - virtual ble_error_t cancel_pairing( - connection_handle_t connection, pairing_failure_t reason - ); - /** * @see ::ble::pal::SecurityManager::get_random_data */ @@ -259,6 +252,11 @@ public: // MITM // + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + /** * @see ::ble::pal::SecurityManager::passkey_request_reply */ @@ -267,6 +265,16 @@ public: passkey_num_t passkey ); + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + /** * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply */ @@ -296,16 +304,6 @@ public: connection_handle_t connection ); - /** - * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply - */ - virtual ble_error_t secure_connections_oob_request_reply( - connection_handle_t connection, - const oob_lesc_value_t &local_random, - const oob_lesc_value_t &peer_random, - const oob_confirm_t &peer_confirm - ); - // singleton of the ARM Cordio Security Manager static CordioSecurityManager &get_security_manager(); @@ -315,6 +313,8 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; + bool _lesc_keys_generated; + uint8_t _public_key_x[SEC_ECC_KEY_LEN]; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 7764bbd09c..2935fdcc41 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include "CordioPalSecurityManager.h" #include "dm_api.h" #include "smp_api.h" @@ -27,7 +29,9 @@ namespace cordio { CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), - _default_passkey(0) + _default_passkey(0), + _lesc_keys_generated(false), + _public_key_x() { } @@ -43,6 +47,17 @@ CordioSecurityManager::~CordioSecurityManager() ble_error_t CordioSecurityManager::initialize() { + // reset local state + _use_default_passkey = false; + _default_passkey = 0; + _lesc_keys_generated = false; + +#if 0 + // FIXME: need help from the stack or local calculation + // generate a new set of keys + DmSecGenerateEccKeyReq(); +#endif + return BLE_ERROR_NONE; } @@ -53,6 +68,7 @@ ble_error_t CordioSecurityManager::terminate() ble_error_t CordioSecurityManager::reset() { + initialize(); return BLE_ERROR_NONE; } @@ -93,6 +109,8 @@ ble_error_t CordioSecurityManager::clear_resolving_list() // Feature support // +// FIXME: Enable when new function available in the pal. +#if 0 ble_error_t CordioSecurityManager::set_secure_connections_support( bool enabled, bool secure_connections_only ) { @@ -104,6 +122,7 @@ ble_error_t CordioSecurityManager::set_secure_connections_support( } return BLE_ERROR_NONE; } +#endif ble_error_t CordioSecurityManager::get_secure_connections_support( bool &enabled @@ -253,12 +272,6 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::generate_public_key() -{ - // FIXME - return BLE_ERROR_NOT_IMPLEMENTED; -} - //////////////////////////////////////////////////////////////////////////// // Global parameters // @@ -380,8 +393,8 @@ ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply( ble_error_t CordioSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { - // FIXME: - return BLE_ERROR_NOT_IMPLEMENTED; + DmSecCompareRsp(connection, confirmation); + return BLE_ERROR_NONE; } // FIXME: remove when declaration from the stack is available @@ -397,6 +410,13 @@ ble_error_t CordioSecurityManager::send_keypress_notification( ble_error_t CordioSecurityManager::generate_secure_connections_oob( connection_handle_t connection ) { + // Note: this is not tie to a connection; only one oob value is present in + // the pal. + + uint8_t oobLocalRandom[SMP_RAND_LEN]; + SecRand(oobLocalRandom, SMP_RAND_LEN); + DmSecCalcOobReq(oobLocalRandom, _public_key_x); + return BLE_ERROR_NOT_IMPLEMENTED; } @@ -406,7 +426,18 @@ ble_error_t CordioSecurityManager::secure_connections_oob_request_reply( const oob_lesc_value_t &peer_random, const oob_confirm_t &peer_confirm ) { - return BLE_ERROR_NOT_IMPLEMENTED; + dmSecLescOobCfg_t oob_config = { 0 }; + + memcpy(oob_config.localRandom, local_random.data(), local_random.size()); + // FIXME: + // memcpy(oob_config.localConfirm, ?, ?); + memcpy(oob_config.peerRandom, peer_random.data(), peer_random.size()); + memcpy(oob_config.peerConfirm, peer_confirm.data(), peer_confirm.size()); + + DmSecSetOob(connection, &oob_config); + DmSecAuthRsp(connection, 0, NULL); + + return BLE_ERROR_NONE; } CordioSecurityManager& CordioSecurityManager::get_security_manager() @@ -416,8 +447,8 @@ CordioSecurityManager& CordioSecurityManager::get_security_manager() } bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { - SecurityManager::EventHandler* handler = - get_security_manager().get_event_handler(); + CordioSecurityManager& self = get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); if ((msg == NULL) || (handler == NULL)) { return false; @@ -479,6 +510,11 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { connection_handle_t connection = evt->hdr.param; if (evt->oob) { + // FIXME: Nothing in the API indicates if smp or sc OOB are + // requested. + // To set secure connection OOB: + // - DmSecSetOob(connection, oob_data) + // - DmSecAuthRsp(connection, 0, NULL) handler->on_legacy_pairing_oob_request(connection); } else if (evt->display) { if (get_security_manager()._use_default_passkey) { @@ -602,18 +638,36 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { return true; } - case DM_SEC_CALC_OOB_IND: + case DM_SEC_CALC_OOB_IND: { + dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg; + handler->on_secure_connections_oob_generated( + evt->hdr.param, + evt->random, + evt->confirm + ); return true; + } - case DM_SEC_ECC_KEY_IND: + case DM_SEC_ECC_KEY_IND: { + secEccMsg_t* evt = (secEccMsg_t*) msg; + DmSecSetEccKey(&evt->data.key); + memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(_public_key_x)); + self._lesc_keys_generated = true; return true; + } - case DM_SEC_COMPARE_IND: + case DM_SEC_COMPARE_IND: { + dmSecCnfIndEvt_t* evt = (dmSecCnfIndEvt_t*) msg; + handler->on_passkey_display( + /* connection */ evt->hdr.param, + DmSecGetCompareValue(evt->confirm) + ); + handler->on_confirmation_request(/* connection */ evt->hdr.param); return true; + } case DM_SEC_KEYPRESS_IND: { dmSecKeypressIndEvt_t* evt = (dmSecKeypressIndEvt_t*) msg; - handler->on_keypress_notification( /* connection */ evt->hdr.param, (Keypress_t) evt->notificationType From 02ba2848a8b0b3f8bbdebd01a8f6e6a6ed530f3a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 26 Mar 2018 17:48:32 +0100 Subject: [PATCH 030/274] avoid recalculating oob fi already calculating --- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 3 +- .../source/generic/GenericSecurityManager.cpp | 36 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index f5ac38497e..a8bccc8142 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -974,7 +974,8 @@ public: ) = 0; /** - * Generate local OOB data to be sent to the application which sends it to the peer.p + * Generate local OOB data to be sent to the application which sends it to the peer. + * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t generate_secure_connections_oob() = 0; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a599868770..a6606e9d64 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -510,17 +510,35 @@ ble_error_t GenericSecurityManager::generateOOB( const address_t *address ) { /* legacy pairing */ - _oob_temporary_key_creator_address = *address; - get_random_data(_oob_temporary_key.buffer(), 16); + ble_error_t status = get_random_data(_oob_temporary_key.buffer(), 16); - eventHandler->legacyPairingOobGenerated( - &_oob_temporary_key_creator_address, - &_oob_temporary_key - ); + if (status == BLE_ERROR_NONE) { + _oob_temporary_key_creator_address = *address; - /* secure connections */ - _oob_local_address = *address; - _pal.generate_secure_connections_oob(); + eventHandler->legacyPairingOobGenerated( + &_oob_temporary_key_creator_address, + &_oob_temporary_key + ); + } else { + return status; + } + + /* Secure connections. Avoid generating if we're already waiting for it. + * If a local random is set to 0 it means we're already calculating + * unless the address is invalid which means we've never done so yet */ + if (_oob_local_random != 0 || _oob_local_address == address_t()) { + status = _pal.generate_secure_connections_oob(); + + if (status == BLE_ERROR_NONE) { + _oob_local_address = *address; + /* this will be updated when calculation completes */ + _oob_local_random = 0; + } else if (status != BLE_ERROR_NOT_IMPLEMENTED) { + return status; + } + } else { + return BLE_STACK_BUSY; + } return BLE_ERROR_NONE; } From d1b4713ae62a3eeecc947654192f6e0425b0e6df Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 26 Mar 2018 17:53:40 +0100 Subject: [PATCH 031/274] removed redundancy --- .../source/generic/GenericSecurityManager.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a6606e9d64..edf758d0dc 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -556,20 +556,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; - /* legacy pairing */ - _oob_temporary_key_creator_address = cb->local_address; - get_random_data(_oob_temporary_key.buffer(), 16); - - eventHandler->legacyPairingOobGenerated( - &_oob_temporary_key_creator_address, - &_oob_temporary_key - ); - - /* secure connections */ - _oob_local_address = cb->local_address; - _pal.generate_secure_connections_oob(); - - return BLE_ERROR_NONE; + return generateOOB(&cb->local_address);; } ble_error_t GenericSecurityManager::confirmationEntered( From e1885486fa46841a914963039ad24bd7ced04030 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 26 Mar 2018 18:00:05 +0100 Subject: [PATCH 032/274] only generate oob if using oob --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index edf758d0dc..29cbc066cc 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -556,7 +556,11 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->attempt_oob = useOOB; cb->oob_mitm_protection = OOBProvidesMITM; - return generateOOB(&cb->local_address);; + if (useOOB) { + return generateOOB(&cb->local_address); + } else { + return BLE_ERROR_NONE; + } } ble_error_t GenericSecurityManager::confirmationEntered( From c54265073436cf2f6defa85eb09d5e066c2ec6ea Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 26 Mar 2018 18:07:29 +0100 Subject: [PATCH 033/274] removed unused param from call --- .../targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 92996ff06f..bff6eef611 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -636,7 +636,6 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { case DM_SEC_CALC_OOB_IND: { dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg; handler->on_secure_connections_oob_generated( - evt->hdr.param, evt->random, evt->confirm ); From aa90f0df652b8686820a62767cd98345b8cbe457 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 27 Mar 2018 12:25:50 +0100 Subject: [PATCH 034/274] rely solely on random vlalue to know if already calculating simplify by setting a fake random value at the start so that first run is the same as subsequent runs --- features/FEATURE_BLE/ble/BLETypes.h | 19 +++++++++++++++++++ .../ble/generic/GenericSecurityManager.h | 5 +++++ .../source/generic/GenericSecurityManager.cpp | 10 +++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 856f3ca84d..1fbde5df4d 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -324,6 +324,25 @@ struct byte_array_t { return _value; } + /** + * Returns true if every byte is equal to zero + */ + bool is_all_zeros() { + for (size_t i = 0; i < array_size; i++) { + if (_value[i] != 0) { + return false; + } + } + return true; + } + + /** + * Zero out all bytes + */ + void set_all_zeros() { + memset(_value, 0x00, array_size); + } + /** * Size in byte of a data. */ diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index b01020b19e..1b16a548fa 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -244,6 +244,11 @@ public: _legacy_pairing_allowed(true), _master_sends_keys(false) { _pal.set_event_handler(this); + + /* We create a fake value for oob to allow creation of the next oob which needs + * the last process to finish first before restarting (this is to simplify checking). + * This fake value will not be used as the oob address is currently invalid */ + _oob_local_random[0] = 1; } //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 29cbc066cc..f93b9efa6e 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -524,15 +524,15 @@ ble_error_t GenericSecurityManager::generateOOB( } /* Secure connections. Avoid generating if we're already waiting for it. - * If a local random is set to 0 it means we're already calculating - * unless the address is invalid which means we've never done so yet */ - if (_oob_local_random != 0 || _oob_local_address == address_t()) { + * If a local random is set to 0 it means we're already calculating. */ + if (!_oob_local_random.is_all_zeros()) { status = _pal.generate_secure_connections_oob(); if (status == BLE_ERROR_NONE) { _oob_local_address = *address; - /* this will be updated when calculation completes */ - _oob_local_random = 0; + /* this will be updated when calculation completes, + * a value of all zeros is an invalid random value */ + _oob_local_random.set_all_zeros(); } else if (status != BLE_ERROR_NOT_IMPLEMENTED) { return status; } From cf6bf9968fe0e933278b39332563ac4520ca9742 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 28 Mar 2018 18:30:01 +0100 Subject: [PATCH 035/274] set peer csrk on pal --- features/FEATURE_BLE/ble/GattClient.h | 9 ++++ .../ble/generic/GenericSecurityManager.h | 13 +++++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 12 +++++ .../source/generic/GenericGattClient.cpp | 23 ++++++++-- .../source/generic/GenericSecurityManager.cpp | 45 ++++++++++++++++--- .../TARGET_CORDIO/CordioPalSecurityManager.h | 8 ++++ .../source/CordioPalSecurityManager.cpp | 8 ++++ 7 files changed, 108 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index 137304bc23..cabfaf9a19 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -116,6 +116,15 @@ public: * The server does not acknowledge the status of the operation. */ GATT_OP_WRITE_CMD = 0x02, + + /** + * Signed Write command. + * + * It is used to request the server to write the value of an attribute + * using a signed packet. The server does not acknowledge the status + * of the operation. + */ + GATT_OP_SIGNED_WRITE_CMD = 0x03 }; /** diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 583097fa76..9d40acec97 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -313,13 +313,24 @@ private: * Returns the CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. - * @param[in] entryKeys security entry containing keys. + * @param[in] csrk connection signature resolving key. */ void return_csrk_cb( pal::SecurityDb::entry_handle_t connection, const csrk_t *csrk ); + /** + * 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. + */ + void set_peer_csrk_cb( + pal::SecurityDb::entry_handle_t connection, + const csrk_t *csrk + ); + /** * Updates the entry for the connection with OOB data presence. * diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 5dca19404b..d99aee2d5c 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -866,6 +866,18 @@ public: const csrk_t &csrk ) = 0; + /** + * Set the peer CSRK for particular connection. + * + * @param[in] connection connection handle + * @param[in] csrk signing key + * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk + ) = 0; + //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 97c6d57fc0..2309d7a79a 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -21,6 +21,8 @@ #include #include "ble/generic/GenericGattClient.h" #include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" +#include "ble/generic/GenericSecurityManager.h" #include using ble::pal::AttServerMessage; @@ -1062,6 +1064,11 @@ ble_error_t GenericGattClient::read( return err; } +#define PREPARE_WRITE_HEADER_LENGTH 5 +#define WRITE_HEADER_LENGTH 3 +#define CMAC_LENGTH 8 +#define MAC_COUNTER_LENGTH 4 + ble_error_t GenericGattClient::write( GattClient::WriteOp_t cmd, Gap::Handle_t connection_handle, @@ -1077,7 +1084,7 @@ ble_error_t GenericGattClient::write( uint16_t mtu = get_mtu(connection_handle); if (cmd == GattClient::GATT_OP_WRITE_CMD) { - if (length > (uint16_t)(mtu - 3)) { + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } return _pal_client->write_without_response( @@ -1085,10 +1092,20 @@ ble_error_t GenericGattClient::write( attribute_handle, make_const_ArrayView(value, length) ); + } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->signed_write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); } else { uint8_t* data = NULL; - if (length > (uint16_t)(mtu - 3)) { + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { data = (uint8_t*) malloc(length); if (data == NULL) { return BLE_ERROR_NO_MEM; @@ -1115,7 +1132,7 @@ ble_error_t GenericGattClient::write( err = _pal_client->queue_prepare_write( connection_handle, attribute_handle, - make_const_ArrayView(value, mtu - 5), + make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), /* offset */ 0 ); } else { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 2acca2755f..59fe4fd822 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -313,17 +313,27 @@ ble_error_t GenericSecurityManager::enableSigning( } cb->signing_requested = enabled; - cb->signing_override_default = false; + cb->signing_override_default = true; if (cb->encrypted) { return BLE_ERROR_INVALID_STATE; } - if (!cb->csrk_stored && cb->signing_requested) { - init_signing(); - if (cb->is_master) { - return requestPairing(connection); + + if (cb->signing_requested) { + if (cb->csrk_stored) { + /* used the stored ones when available */ + _db.get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); } else { - return slave_security_request(connection); + /* crate keys if needed and exchange them */ + init_signing(); + if (cb->is_master) { + return requestPairing(connection); + } else { + return slave_security_request(connection); + } } } @@ -698,6 +708,18 @@ void GenericSecurityManager::set_ltk_cb( } } +void GenericSecurityManager::set_peer_csrk_cb( + pal::SecurityDb::entry_handle_t db_entry, + const csrk_t *csrk +) { + ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } + + _pal.set_peer_csrk(cb->connection, *csrk); +} + void GenericSecurityManager::return_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, const csrk_t *csrk @@ -772,6 +794,17 @@ void GenericSecurityManager::on_connected( if (dist_flags) { *static_cast(cb) = *dist_flags; } + + const bool signing = cb->signing_override_default ? + cb->signing_requested + : _default_key_distribution.get_signing(); + + if (signing && cb->csrk_stored) { + _db.get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); + } } void GenericSecurityManager::on_disconnected( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 458f20311c..dbc4346725 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -239,6 +239,14 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk + ); + //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 2935fdcc41..c5a1c15811 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -272,6 +272,14 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) return BLE_ERROR_NONE; } +ble_error_t CordioSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk +) { + /* TODO implement */ + return BLE_ERROR_NOT_IMPLEMENTED; +} + //////////////////////////////////////////////////////////////////////////// // Global parameters // From b25c2330c1be95c7ebbf2aec9b4fa41027b12a43 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 13:46:26 +0100 Subject: [PATCH 036/274] invalid mic event --- .../FEATURE_BLE/ble/generic/GenericSecurityManager.h | 6 ++++++ features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 10 ++++++++++ .../source/generic/GenericSecurityManager.cpp | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 9d40acec97..42ef0075b6 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -514,6 +514,12 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_invalid_mic + */ + virtual void on_invalid_mic( + connection_handle_t connection + ); + /** @copydoc ble::pal::SecurityManager::on_slave_security_request */ virtual void on_slave_security_request( diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index d99aee2d5c..875f0d0e85 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -280,6 +280,16 @@ public: connection_handle_t connection ) = 0; + /** + * Indicate that the MIC verification has failed. This could + * be due to an invalid CSRK key. + * + * @param[in] connection connection handle + */ + virtual void on_invalid_mic( + connection_handle_t connection + ) = 0; + /** * Ask the stack to evaluate the security request received from the slave. * This might result in the stack enabling encryption, or pairing/re-pairing. diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 59fe4fd822..ab88acff66 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -909,6 +909,11 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } +void GenericSecurityManager::on_invalid_mic(connection_handle_t connection) { + (void)connection; + /* TODO: count and re-pair when threshold reached */ +} + void GenericSecurityManager::on_slave_security_request( connection_handle_t connection, AuthenticationMask authentication From eb66461e295fcb823d71a1f73dc6e5f2ef3f6bf8 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 13:47:22 +0100 Subject: [PATCH 037/274] signing only for the slave, unless keys requested to be sent by master --- .../source/generic/GenericSecurityManager.cpp | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index ab88acff66..ff14a5b6e2 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -140,14 +140,10 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio * use when roles are changed */ if (_master_sends_keys) { initiator_distribution = _default_key_distribution; - } - - /* override default if requested */ - if (cb->signing_override_default) { - initiator_distribution.set_signing(cb->signing_requested); - } else { - /* because _master_sends_keys might be false so we need to set this */ - initiator_distribution.set_signing(_default_key_distribution.get_signing()); + /* override default if requested */ + if (cb->signing_override_default) { + initiator_distribution.set_signing(cb->signing_requested); + } } KeyDistribution responder_distribution(_default_key_distribution); @@ -312,14 +308,10 @@ ble_error_t GenericSecurityManager::enableSigning( return BLE_ERROR_INVALID_PARAM; } - cb->signing_requested = enabled; cb->signing_override_default = true; - if (cb->encrypted) { - return BLE_ERROR_INVALID_STATE; - } - - if (cb->signing_requested) { + if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { + cb->signing_requested = true; if (cb->csrk_stored) { /* used the stored ones when available */ _db.get_entry_peer_csrk( @@ -335,6 +327,8 @@ ble_error_t GenericSecurityManager::enableSigning( return slave_security_request(connection); } } + } else { + cb->signing_requested = enabled; } return BLE_ERROR_NONE; From c36a8d7dba1a16b32479cc3fbc0e5fcd8c01c29a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:24:40 +0100 Subject: [PATCH 038/274] let the stack know whether csrk is authenticated --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 3 ++- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 5 ++++- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 3 ++- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 875f0d0e85..05f624e5c5 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -885,7 +885,8 @@ public: */ virtual ble_error_t set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ) = 0; //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index ff14a5b6e2..a41035e474 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -711,7 +711,10 @@ void GenericSecurityManager::set_peer_csrk_cb( return; } - _pal.set_peer_csrk(cb->connection, *csrk); + _pal.set_peer_csrk( + cb->connection, + *csrk, + cb->csrk_mitm_protected); } void GenericSecurityManager::return_csrk_cb( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index dbc4346725..564ecf9856 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -244,7 +244,8 @@ public: */ virtual ble_error_t set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ); //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index c5a1c15811..df1b55b652 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -274,7 +274,8 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) ble_error_t CordioSecurityManager::set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ) { /* TODO implement */ return BLE_ERROR_NOT_IMPLEMENTED; From 45c22ac12e67780bd21b710d582bc660a38af406 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:44:15 +0100 Subject: [PATCH 039/274] count failures, trigger reparing when verification fails --- .../ble/generic/GenericSecurityManager.h | 4 +++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 4 ++-- .../source/generic/GenericSecurityManager.cpp | 21 +++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 42ef0075b6..177be864a8 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -445,6 +445,8 @@ private: uint8_t oob_mitm_protection:1; uint8_t oob_present:1; uint8_t legacy_pairing_oob_request_pending:1; + + uint8_t mic_failures:2; }; pal::SecurityManager &_pal; @@ -516,7 +518,7 @@ public: /** @copydoc ble::pal::SecurityManager::on_invalid_mic */ - virtual void on_invalid_mic( + virtual void on_signature_verification_failure( connection_handle_t connection ); diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 05f624e5c5..865ddaa4d1 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -281,12 +281,12 @@ public: ) = 0; /** - * Indicate that the MIC verification has failed. This could + * Indicate that signed data was rejected due to verification failure. This could * be due to an invalid CSRK key. * * @param[in] connection connection handle */ - virtual void on_invalid_mic( + virtual void on_signature_verification_failure( connection_handle_t connection ) = 0; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a41035e474..c5e154dbff 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -906,9 +906,21 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } -void GenericSecurityManager::on_invalid_mic(connection_handle_t connection) { - (void)connection; - /* TODO: count and re-pair when threshold reached */ +void GenericSecurityManager::on_signature_verification_failure(connection_handle_t connection) { + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + + cb->mic_failures++; + if (cb->mic_failures == 3) { + cb->mic_failures = 0; + if (cb->is_master) { + requestPairing(connection); + } else { + slave_security_request(connection); + } + } } void GenericSecurityManager::on_slave_security_request( @@ -1225,7 +1237,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : attempt_oob(false), oob_mitm_protection(false), oob_present(false), - legacy_pairing_oob_request_pending(false) { } + legacy_pairing_oob_request_pending(false), + mic_failures(0) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { From c0f390f2cd8b2222ae472a56069ae8c657b47ffd Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:47:50 +0100 Subject: [PATCH 040/274] fixed naming for sig failure count --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 2 +- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 177be864a8..b615dce498 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -446,7 +446,7 @@ private: uint8_t oob_present:1; uint8_t legacy_pairing_oob_request_pending:1; - uint8_t mic_failures:2; + uint8_t csrk_failures:2; }; pal::SecurityManager &_pal; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index c5e154dbff..1199cd88e0 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -912,9 +912,9 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle return; } - cb->mic_failures++; - if (cb->mic_failures == 3) { - cb->mic_failures = 0; + cb->csrk_failures++; + if (cb->csrk_failures == 3) { + cb->csrk_failures = 0; if (cb->is_master) { requestPairing(connection); } else { @@ -1238,7 +1238,7 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : oob_mitm_protection(false), oob_present(false), legacy_pairing_oob_request_pending(false), - mic_failures(0) { } + csrk_failures(0) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { From cfa53d5e6c67c441cba6df87b56dbac6dc4e7508 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:02:27 +0100 Subject: [PATCH 041/274] only bother reacting to verification failures if we want to use signing --- .../source/generic/GenericSecurityManager.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 1199cd88e0..9aed7b9bd9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -912,13 +912,19 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle return; } - cb->csrk_failures++; - if (cb->csrk_failures == 3) { - cb->csrk_failures = 0; - if (cb->is_master) { - requestPairing(connection); - } else { - slave_security_request(connection); + const bool signing = cb->signing_override_default ? + cb->signing_requested + : _default_key_distribution.get_signing(); + + if (signing) { + cb->csrk_failures++; + if (cb->csrk_failures == 3) { + cb->csrk_failures = 0; + if (cb->is_master) { + requestPairing(connection); + } else { + slave_security_request(connection); + } } } } From b979c4a2c8249176e19445baa861f5913ccc705d Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:24:20 +0100 Subject: [PATCH 042/274] style fix --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 9aed7b9bd9..17a1bb8460 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -906,7 +906,9 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } -void GenericSecurityManager::on_signature_verification_failure(connection_handle_t connection) { +void GenericSecurityManager::on_signature_verification_failure( + connection_handle_t connection +) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -921,9 +923,9 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle if (cb->csrk_failures == 3) { cb->csrk_failures = 0; if (cb->is_master) { - requestPairing(connection); + requestPairing(connection); } else { - slave_security_request(connection); + slave_security_request(connection); } } } From cdbead87eaa86b83122b7b1975af6e7376517b28 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:53:54 +0100 Subject: [PATCH 043/274] style fix --- .../source/generic/GenericGattClient.cpp | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 2309d7a79a..759b707444 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1081,20 +1081,19 @@ ble_error_t GenericGattClient::write( return BLE_ERROR_INVALID_STATE; } - uint16_t mtu = get_mtu(connection_handle); + uint16_t mtu = get_mtu(connection_handle); - if (cmd == GattClient::GATT_OP_WRITE_CMD) { - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - return _pal_client->write_without_response( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { - - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { + if (cmd == GattClient::GATT_OP_WRITE_CMD) { + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->write_without_response( + connection_handle, + attribute_handle, + ); + } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + /*TODO check encryption status */ + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } return _pal_client->signed_write_without_response( @@ -1102,56 +1101,56 @@ ble_error_t GenericGattClient::write( attribute_handle, make_const_ArrayView(value, length) ); - } else { - uint8_t* data = NULL; + } else { + uint8_t* data = NULL; - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { - data = (uint8_t*) malloc(length); - if (data == NULL) { - return BLE_ERROR_NO_MEM; - } - memcpy(data, value, length); - } + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } - WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock( - connection_handle, - attribute_handle, - data, - length - ); + WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock( + connection_handle, + attribute_handle, + data, + length + ); - if (write_pcb == NULL) { - free(data); - return BLE_ERROR_NO_MEM; - } + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } - insert_control_block(write_pcb); + insert_control_block(write_pcb); - ble_error_t err = BLE_ERROR_UNSPECIFIED; - if (data) { - err = _pal_client->queue_prepare_write( - connection_handle, - attribute_handle, - make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), - /* offset */ 0 - ); - } else { - err = _pal_client->write_attribute( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (data) { + err = _pal_client->queue_prepare_write( + connection_handle, + attribute_handle, + make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), + /* offset */0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } - if (err) { - remove_control_block(write_pcb); - delete write_pcb; - } + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } - return err; - } + return err; + } - return BLE_ERROR_NOT_IMPLEMENTED; + return BLE_ERROR_NOT_IMPLEMENTED; } void GenericGattClient::onServiceDiscoveryTermination( From ced41b425da7c3f14ade39945f48fd1d9a079c2f Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:56:32 +0100 Subject: [PATCH 044/274] missing line from commit (github client fail) --- features/FEATURE_BLE/source/generic/GenericGattClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 759b707444..a6d1d0692e 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1090,6 +1090,7 @@ ble_error_t GenericGattClient::write( return _pal_client->write_without_response( connection_handle, attribute_handle, + make_const_ArrayView(value, length) ); } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { /*TODO check encryption status */ From 95cd37b49113b7d9e49dd700a11a332863d4531a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 29 Mar 2018 17:22:48 +0100 Subject: [PATCH 045/274] BLE: Add const overload for byte_array_t subscribt operator. --- features/FEATURE_BLE/ble/BLETypes.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 856f3ca84d..dbeadfe316 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -310,6 +310,13 @@ struct byte_array_t { return _value[i]; } + /** + * Subscript operator to access data content + */ + uint8_t operator[](uint8_t i) const { + return _value[i]; + } + /** * Return the pointer to the buffer holding data. */ From 3218e7980533cc17c1bb71ea6772d3e5114def37 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 29 Mar 2018 17:23:24 +0100 Subject: [PATCH 046/274] BLE: Fix reference to security manager in Nordic event handler. --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp index d3b63c211b..32e1e3df0c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp @@ -185,7 +185,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); nRF5xGap &gap = (nRF5xGap &) ble.getGap(); nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer(); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager(); /* Custom event handler */ switch (p_ble_evt->header.evt_id) { From f0e18fa007335a5ace2cd202cbd48e2e392c9315 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 29 Mar 2018 17:23:54 +0100 Subject: [PATCH 047/274] BLE: Add LESC crypto toolbox for Nordic. --- .../TARGET_NRF5/source/nRF5XCrypto.cpp | 140 ++++++++++++++++++ .../TARGET_NRF5/source/nRF5xCrypto.h | 71 +++++++++ 2 files changed, 211 insertions(+) create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp new file mode 100644 index 0000000000..9c6cb00232 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -0,0 +1,140 @@ +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include +#include + + +#include "mbedtls/platform.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "platform/CriticalSectionLock.h" +#include "ble/BLETypes.h" +#include "cmsis.h" +#include "nRF5xCrypto.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +LescCrypto::LescCrypto() : _initialized(false) { + mbedtls_entropy_init(&_entropy_context); + mbedtls_ecp_group_init(&_group); + int err = mbedtls_ecp_group_load( + &_group, + MBEDTLS_ECP_DP_SECP256R1 + ); + _initialized = err ? false : true; +} + +LescCrypto::~LescCrypto() { + mbedtls_ecp_group_free(&_group); + mbedtls_entropy_free(&_entropy_context); +} + +bool LescCrypto::generate_keys( + ble::public_key_coord_t& X, + ble::public_key_coord_t& Y, + ble::public_key_coord_t& secret +) { + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + int err = mbedtls_ecp_gen_keypair( + &_group, + &secret_key, + &public_keys, + mbedtls_entropy_func, + &_entropy_context + ); + + if (!err) { + store_mpi(secret, secret_key); + store_mpi(X, public_keys.X); + store_mpi(Y, public_keys.Y); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + + return err ? false : true; +} + +bool LescCrypto::generate_shared_secret( + const ble::public_key_coord_t& peer_X, + const ble::public_key_coord_t& peer_Y, + const ble::public_key_coord_t& own_secret, + ble::public_key_coord_t& shared_secret +) { + mbedtls_mpi result; + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&result); + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + load_mpi(secret_key, own_secret); + load_mpi(public_keys.X, peer_X); + load_mpi(public_keys.Y, peer_Y); + mbedtls_mpi_lset( &public_keys.Z, 1 ); + + int err = mbedtls_ecdh_compute_shared( + &_group, + &result, + &public_keys, + &secret_key, + /* rng function; optional */ NULL, + /* rng param */ NULL + ); + + if (!err) { + store_mpi(shared_secret, result); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + mbedtls_mpi_free(&result); + + return err ? false : true; +} + + +void LescCrypto::load_mpi(mbedtls_mpi& dest, const ble::public_key_coord_t& src) { + ble::public_key_coord_t src_be = src; + swap_endian(src_be); + mbedtls_mpi_read_binary(&dest, src_be.buffer(), src_be.size()); +} + +void LescCrypto::store_mpi(ble::public_key_coord_t& dest, const mbedtls_mpi& src) { + mbedtls_mpi_write_binary(&src, dest.buffer(), dest.size()); + swap_endian(dest); +} + +void LescCrypto::swap_endian(ble::public_key_coord_t& to_swap) { + swap_endian(to_swap.buffer(), to_swap.size()); +} + +void LescCrypto::swap_endian(uint8_t* buf, size_t len) { + for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { + std::swap(buf[low], buf[high]); + } +} + +} // nordic +} // vendor +} // pal +} // ble + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h new file mode 100644 index 0000000000..1478d4213f --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -0,0 +1,71 @@ +#ifndef NRF5X_CRYPTO_ +#define NRF5X_CRYPTO_ + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include +#include + + +#include "mbedtls/platform.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "platform/CriticalSectionLock.h" +#include "ble/BLETypes.h" +#include "cmsis.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +class LescCrypto : mbed::NonCopyable { + +public: + LescCrypto(); + + ~LescCrypto(); + + bool generate_keys( + ble::public_key_coord_t& X, + ble::public_key_coord_t& Y, + ble::public_key_coord_t& secret + ); + + bool generate_shared_secret( + const ble::public_key_coord_t& peer_X, + const ble::public_key_coord_t& peer_Y, + const ble::public_key_coord_t& own_secret, + ble::public_key_coord_t& shared_secret + ); + +private: + + void load_mpi(mbedtls_mpi& dest, const ble::public_key_coord_t& src); + + void store_mpi(ble::public_key_coord_t& dest, const mbedtls_mpi& src); + + void swap_endian(ble::public_key_coord_t& to_swap); + + void swap_endian(uint8_t* buf, size_t len); + + bool _initialized; + mbedtls_entropy_context _entropy_context; + mbedtls_ecp_group _group; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif // NRF5X_CRYPTO_ From 3272863f8374f92866468da0bf88ad9321278b96 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 29 Mar 2018 17:24:46 +0100 Subject: [PATCH 048/274] BLE Nordic: Support LESC. --- .../source/nRF5xPalSecurityManager.cpp | 183 ++++++++++++++---- .../source/nRF5xPalSecurityManager.h | 32 +-- 2 files changed, 157 insertions(+), 58 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index adf5572f58..cce5cf1d83 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -76,6 +76,11 @@ struct nRF5xSecurityManager::pairing_control_block_t { ble_gap_id_key_t peer_id_key; ble_gap_sign_info_t peer_sign_key; ble_gap_lesc_p256_pk_t peer_pk; + + // flag required to help DHKey computation/process; should be removed with + // later versions of the softdevice + uint8_t own_oob:1; + uint8_t peer_oob:1; }; nRF5xSecurityManager::nRF5xSecurityManager() @@ -90,7 +95,7 @@ nRF5xSecurityManager::nRF5xSecurityManager() nRF5xSecurityManager::~nRF5xSecurityManager() { - + terminate(); } //////////////////////////////////////////////////////////////////////////// @@ -99,19 +104,27 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { - // FIXME: generate and set public and private keys - return BLE_ERROR_NONE; + if (_crypto.generate_keys(X, Y, secret)) { + return BLE_ERROR_NONE; + } + + return BLE_ERROR_INTERNAL_STACK_FAILURE; } ble_error_t nRF5xSecurityManager::terminate() { + release_all_pairing_cb(); return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::reset() { - // FIXME: reset public and private keys - return BLE_ERROR_NONE; + ble_error_t err = terminate(); + if (err) { + return err; + } + + return initialize(); } //////////////////////////////////////////////////////////////////////////// @@ -162,6 +175,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_request( KeyDistribution initiator_dist, KeyDistribution responder_dist ) { + printf("nRF5xSecurityManager::send_pairing_request\r\n"); // allocate the control block required for the procedure completion pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); if (!pairing_cb) { @@ -173,6 +187,10 @@ ble_error_t nRF5xSecurityManager::send_pairing_request( initiator_dist.set_signing(false); responder_dist.set_signing(false); + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + ble_gap_sec_params_t security_params = make_security_params( oob_data_flag, authentication_requirements, @@ -209,6 +227,10 @@ ble_error_t nRF5xSecurityManager::send_pairing_response( initiator_dist.set_signing(false); responder_dist.set_signing(false); + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + ble_gap_sec_params_t security_params = make_security_params( oob_data_flag, authentication_requirements, @@ -239,7 +261,7 @@ ble_error_t nRF5xSecurityManager::send_pairing_response( ble_error_t nRF5xSecurityManager::cancel_pairing( connection_handle_t connection, pairing_failure_t reason ) { - // this is the default path except when a key is expected to be enterred by + // this is the default path except when a key is expected to be entered by // the user. uint32_t err = sd_ble_gap_sec_params_reply( connection, @@ -272,9 +294,7 @@ ble_error_t nRF5xSecurityManager::cancel_pairing( ble_error_t nRF5xSecurityManager::get_secure_connections_support( bool &enabled ) { - // NRF5x platforms support secure connections - // FIXME: set to true once the ECC library is included - enabled = false; + enabled = true; return BLE_ERROR_NONE; } @@ -399,7 +419,7 @@ ble_error_t nRF5xSecurityManager::encrypt_data( const byte_array_t<16> &key, encryption_block_t &data ) { - // FIXME: With signing ? + // FIXME: Implement in LescCrypto ? return BLE_ERROR_NOT_IMPLEMENTED; } @@ -446,8 +466,8 @@ ble_error_t nRF5xSecurityManager::set_ltk( uint32_t err = sd_ble_gap_sec_info_reply( connection, &enc_info, - NULL, - NULL // Not supported + /* id info */ NULL, + /* sign info */ NULL // Not supported ); return convert_sd_error(err); @@ -520,6 +540,11 @@ ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) ble_error_t nRF5xSecurityManager::passkey_request_reply( connection_handle_t connection, const passkey_num_t passkey ) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + PasskeyAscii pkasc(passkey); uint32_t err = sd_ble_gap_auth_key_reply( connection, @@ -530,6 +555,37 @@ ble_error_t nRF5xSecurityManager::passkey_request_reply( return convert_sd_error(err); } +ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + ble_gap_lesc_oob_data_t oob_own; + ble_gap_lesc_oob_data_t oob_peer; + + // is own address important ? + memcpy(oob_own.r, local_random.data(), local_random.size()); + // FIXME: What to do with local confirm ??? + + // is peer address important ? + memcpy(oob_peer.r, peer_random.data(), peer_random.size()); + memcpy(oob_peer.c, peer_confirm.data(), peer_confirm.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_set( + connection, + pairing_cb->own_oob ? &oob_own : NULL, + pairing_cb->peer_oob ? &oob_peer : NULL + ); + + return convert_sd_error(err); +} + ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( connection_handle_t connection, const oob_tk_t& oob_data @@ -546,11 +602,17 @@ ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( ble_error_t nRF5xSecurityManager::confirmation_entered( connection_handle_t connection, bool confirmation ) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + uint32_t err = sd_ble_gap_auth_key_reply( connection, confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE, NULL ); + return convert_sd_error(err); } @@ -568,25 +630,26 @@ ble_error_t nRF5xSecurityManager::send_keypress_notification( ble_error_t nRF5xSecurityManager::generate_secure_connections_oob( connection_handle_t connection ) { - // FIXME: made with external library; requires SDK v13 - return BLE_ERROR_NOT_IMPLEMENTED; -} + ble_gap_lesc_p256_pk_t own_secret; + ble_gap_lesc_oob_data_t oob_data; + memcpy(own_secret.pk, secret.buffer(), secret.size()); -ble_error_t nRF5xSecurityManager::secure_connections_oob_received( - const address_t &address, - const oob_lesc_value_t &random, - const oob_confirm_t &confirm -) { - // FIXME: store locally - return BLE_ERROR_NOT_IMPLEMENTED; -} + uint32_t err = sd_ble_gap_lesc_oob_data_get( + connection, + &own_secret, + &oob_data + ); -bool nRF5xSecurityManager::is_secure_connections_oob_present( - const address_t &address -) { - // FIXME: lookup local store - return false; + if (!err) { + get_event_handler()->on_secure_connections_oob_generated( + connection, + oob_data.r, + oob_data.c + ); + } + + return convert_sd_error(err); } nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() @@ -653,18 +716,15 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) ); } } else { - AuthenticationMask authentication_requirements( - params.bond, - params.mitm, - params.lesc, - params.keypress - ); - - handler->on_pairing_request( connection, params.oob, - authentication_requirements, + AuthenticationMask( + params.bond, + params.mitm, + params.lesc, + params.keypress + ), initiator_dist, responder_dist ); @@ -695,7 +755,11 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) PasskeyAscii::to_num(req.passkey) ); } else { - // FIXME handle this case for secure pairing + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + handler->on_confirmation_request(connection); } return true; @@ -708,6 +772,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) ); return true; } + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { uint8_t key_type = gap_evt.params.auth_key_request.key_type; @@ -727,9 +792,32 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) return true; } - case BLE_GAP_EVT_LESC_DHKEY_REQUEST: - // FIXME: Add with LESC support + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: { + const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = + gap_evt.params.lesc_dhkey_request; + + size_t key_size = public_key_coord_t::size(); + public_key_coord_t peer_X(dhkey_request.p_pk_peer->pk, key_size); + public_key_coord_t peer_Y(dhkey_request.p_pk_peer->pk + key_size, key_size); + public_key_coord_t sh_secret; + ble_gap_lesc_dhkey_t shared_secret; + + _crypto.generate_shared_secret( + peer_X, + peer_Y, + self.secret, + sh_secret + ); + + memcpy(shared_secret.key, sh_secret.data(), sh_secret.size()); + sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret); + + if (dhkey_request.oobd_req) { + handler->on_secure_connections_oob_request(connection); + } + return true; + } case BLE_GAP_EVT_AUTH_STATUS: { const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status; @@ -954,13 +1042,13 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL, own_dist->get_identity() ? &pairing_cb.own_id_key : NULL, own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL, - own_dist->get_link() ? &pairing_cb.own_pk : NULL + &pairing_cb.own_pk }, /* keys_peer */ { peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL, peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL, peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL, - peer_dist->get_link() ? &pairing_cb.peer_pk : NULL + &pairing_cb.peer_pk } }; @@ -969,6 +1057,10 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size()); } + // copy public keys used + memcpy(pairing_cb.own_pk.pk, X.data(), X.size()); + memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size()); + return keyset; } @@ -1016,6 +1108,13 @@ nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection) return NULL; } +void nRF5xSecurityManager::release_all_pairing_cb() +{ + while(_control_blocks) { + release_pairing_cb(_control_blocks); + } +} + } // nordic } // vendor } // pal diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index add7d4e6ce..f9263998ad 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -20,6 +20,7 @@ #include "ble/BLETypes.h" #include "ble/pal/PalSecurityManager.h" #include "nrf_ble.h" +#include "nRF5xCrypto.h" namespace ble { namespace pal { @@ -264,6 +265,16 @@ public: passkey_num_t passkey ); + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + /** * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply */ @@ -293,22 +304,6 @@ public: connection_handle_t connection ); - /** - * @see ::ble::pal::SecurityManager::secure_connections_oob_received - */ - virtual ble_error_t secure_connections_oob_received( - const address_t &address, - const oob_lesc_value_t &random, - const oob_confirm_t &confirm - ); - - /** - * @see ::ble::pal::SecurityManager::is_secure_connections_oob_present - */ - virtual bool is_secure_connections_oob_present( - const address_t &address - ); - // singleton of nordic Security Manager static nRF5xSecurityManager& get_security_manager(); @@ -339,8 +334,13 @@ private: pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection); void release_pairing_cb(pairing_control_block_t* pairing_cb); pairing_control_block_t* get_pairing_cb(connection_handle_t connection); + void release_all_pairing_cb(); pairing_control_block_t* _control_blocks; + LescCrypto _crypto; + ble::public_key_coord_t X; + ble::public_key_coord_t Y; + ble::public_key_coord_t secret; }; } // nordic From 15fd2f33f4801201f6c8510935887f73a281454b Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 09:57:58 +0100 Subject: [PATCH 049/274] typos, style and other review fixes --- .../ble/generic/GenericSecurityManager.h | 2 +- .../source/generic/GenericGattClient.cpp | 10 +++++----- .../source/generic/GenericSecurityManager.cpp | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index b615dce498..a00c4e1e23 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -516,7 +516,7 @@ public: connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_invalid_mic + /** @copydoc ble::pal::SecurityManager::on_signature_verification_failure */ virtual void on_signature_verification_failure( connection_handle_t connection diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index a6d1d0692e..4962b9dd2b 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -40,6 +40,11 @@ using ble::pal::AttHandleValueIndication; using ble::pal::AttHandleValueNotification; using ble::pal::AttFindInformationResponse; +#define PREPARE_WRITE_HEADER_LENGTH 5 +#define WRITE_HEADER_LENGTH 3 +#define CMAC_LENGTH 8 +#define MAC_COUNTER_LENGTH 4 + namespace ble { namespace generic { @@ -1064,11 +1069,6 @@ ble_error_t GenericGattClient::read( return err; } -#define PREPARE_WRITE_HEADER_LENGTH 5 -#define WRITE_HEADER_LENGTH 3 -#define CMAC_LENGTH 8 -#define MAC_COUNTER_LENGTH 4 - ble_error_t GenericGattClient::write( GattClient::WriteOp_t cmd, Gap::Handle_t connection_handle, diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 17a1bb8460..cbe5a250ef 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -319,7 +319,7 @@ ble_error_t GenericSecurityManager::enableSigning( cb->db_entry ); } else { - /* crate keys if needed and exchange them */ + /* create keys if needed and exchange them */ init_signing(); if (cb->is_master) { return requestPairing(connection); @@ -714,7 +714,8 @@ void GenericSecurityManager::set_peer_csrk_cb( _pal.set_peer_csrk( cb->connection, *csrk, - cb->csrk_mitm_protected); + cb->csrk_mitm_protected + ); } void GenericSecurityManager::return_csrk_cb( @@ -793,8 +794,8 @@ void GenericSecurityManager::on_connected( } const bool signing = cb->signing_override_default ? - cb->signing_requested - : _default_key_distribution.get_signing(); + cb->signing_requested : + _default_key_distribution.get_signing(); if (signing && cb->csrk_stored) { _db.get_entry_peer_csrk( @@ -915,8 +916,8 @@ void GenericSecurityManager::on_signature_verification_failure( } const bool signing = cb->signing_override_default ? - cb->signing_requested - : _default_key_distribution.get_signing(); + cb->signing_requested : + _default_key_distribution.get_signing(); if (signing) { cb->csrk_failures++; From 3c1a5a4a56f4806594d52974f610e521c5162cf5 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 12:16:49 +0100 Subject: [PATCH 050/274] incorrect retval usage fixed --- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index a8bccc8142..1833c8bda5 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -544,21 +544,21 @@ public: /** * Initialise stack. Called before first use. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t initialize() = 0; /** * Finalise all actions. Called before shutdown. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t terminate() = 0; /** * Reset to same state as after initialize. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t reset() = 0; @@ -573,7 +573,7 @@ public: * @warning: The number of entries is considered fixed. * * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.41 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual uint8_t read_resolving_list_capacity() = 0; @@ -584,7 +584,7 @@ public: * @param[in] peer_identity_address address of the device whose entry is to be added * @param[in] peer_irk peer identity resolving key * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.38 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t add_device_to_resolving_list( advertising_peer_address_type_t peer_identity_address_type, @@ -598,7 +598,7 @@ public: * @param[in] peer_identity_address_type public/private indicator * @param[in] peer_identity_address address of the device whose entry is to be removed * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.39 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, @@ -609,7 +609,7 @@ public: * Remove all devices from the resolving list. * * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.40 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t clear_resolving_list() = 0; @@ -626,7 +626,7 @@ public: * @param[in] initiator_dist key distribution * @param[in] responder_dist key distribution * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.1 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_pairing_request( connection_handle_t connection, @@ -645,7 +645,7 @@ public: * @param[in] authentication_requirements authentication requirements * @param[in] initiator_dist key distribution * @param[in] responder_dist key distribution - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_pairing_response( connection_handle_t connection, @@ -661,7 +661,7 @@ public: * @param[in] connection connection handle * @param[in] reason pairing failure error * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.5 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t cancel_pairing( connection_handle_t connection, @@ -676,7 +676,7 @@ public: * Check if the Secure Connections feature is supported by the stack and controller. * * @param[out] enabled true if SC are supported - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_secure_connections_support( bool &enabled @@ -686,7 +686,7 @@ public: * Set the IO capability that will be used during pairing feature exchange. * * @param[in] io_capability type of IO capabilities available on the local device - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_io_capability( io_capability_t io_capability @@ -702,7 +702,7 @@ public: * * @param[in] connection connection handle * @param[in] timeout_in_10ms time measured in units of 10 milliseconds - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_authentication_timeout( connection_handle_t connection, @@ -715,7 +715,7 @@ public: * * @param[in] connection connection handle * @param[out] timeout_in_10ms time measured in units of 10 milliseconds - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_authentication_timeout( connection_handle_t connection, @@ -733,7 +733,7 @@ public: * required for pairing. This value shall be in the range * [min_encryption_key_size : 16]. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_encryption_key_requirements( uint8_t min_encryption_key_size, @@ -748,7 +748,7 @@ public: * * @param[in] connection connection handle * @param[in] authentication authentication requirements - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t slave_security_request( connection_handle_t connection, @@ -769,7 +769,7 @@ public: * @param[in] ediv encryption diversifier from the peer * @param[in] rand random value from the peer * @param[in] mitm does the LTK have man in the middle protection - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t enable_encryption( connection_handle_t connection, @@ -786,7 +786,7 @@ public: * @param[in] connection connection handle * @param[in] ltk long term key from the peer * @param[in] mitm does the LTK have man in the middle protection - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t enable_encryption( connection_handle_t connection, @@ -800,7 +800,7 @@ public: * * @param[in] key encryption key * @param[in,out] data data to be encrypted, if successful contains the result - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t encrypt_data( const byte_array_t<16> &key, @@ -826,7 +826,7 @@ public: * @param[in] ltk long term key * @param[in] mitm does the LTK have man in the middle protection * @param[in] secure_connections is this a secure_connections pairing - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_ltk( connection_handle_t connection, @@ -839,7 +839,7 @@ public: * Inform the stack we don't have the LTK. * * @param[in] connection connection handle - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_ltk_not_found( connection_handle_t connection @@ -849,7 +849,7 @@ public: * Set the local IRK. * * @param[in] irk identity resolution key - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_irk( const irk_t &irk @@ -859,7 +859,7 @@ public: * Set the local CSRK. * * @param[in] csrk signing key - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_csrk( const csrk_t &csrk @@ -874,7 +874,7 @@ public: * * @param[out] random_data returns 8 octets of random data * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part H 2 - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t get_random_data( byte_array_t<8> &random_data @@ -902,7 +902,7 @@ public: * passkey is set to 0 then the security manager generates a random * passkey every time it calls SecurityManagerEvent::on_passkey_display. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_display_passkey( passkey_num_t passkey @@ -911,7 +911,7 @@ public: /** * Reply to a passkey request received from the SecurityManagerEventHandler. * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t passkey_request_reply( connection_handle_t connection, @@ -926,7 +926,7 @@ public: * @param[in] peer_random random number used to generate the confirmation on peer * @param[in] peer_confirm confirmation value to be use for authentication * in secure connections pairing - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t secure_connections_oob_request_reply( connection_handle_t connection, @@ -940,7 +940,7 @@ public: * * @param[in] connection connection handle * @param[in] oob_data pointer to out of band data - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t legacy_pairing_oob_request_reply( connection_handle_t connection, @@ -953,7 +953,7 @@ public: * * @param[in] connection connection handle * @param[in] confirmation true if the user indicated the numbers match - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t confirmation_entered( connection_handle_t connection, @@ -966,7 +966,7 @@ public: * * @param[in] connection connection handle * @param[in] keypress type of keypress event - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t send_keypress_notification( connection_handle_t connection, @@ -975,7 +975,7 @@ public: /** * Generate local OOB data to be sent to the application which sends it to the peer. - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t generate_secure_connections_oob() = 0; From ba5b0f30d2945f64869ed7de771c11d3b599ed4a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 13:54:29 +0100 Subject: [PATCH 051/274] added comments about address for oob generation --- features/FEATURE_BLE/ble/SecurityManager.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 9bf6ea26bc..139e61b68d 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -740,7 +740,9 @@ public: * also generate Secure Connections OOB data on top of legacy pairing OOB data. This can be used * to generate such data before any connections take place. * - * @param[in] address The local address you will use in the connection using this OOB data. + * @param[in] address The local address you will use in the connection using this OOB data. This + * address will be returned along with the rest of the OOB data when generation + * is complete. Using an invalid address is illegal. * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ virtual ble_error_t generateOOB(const ble::address_t *address) { From 0a494a0bbca689f2eaa34eaba1f92cbbe5416f8c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 14:47:27 +0100 Subject: [PATCH 052/274] all_zeros now free functions --- features/FEATURE_BLE/ble/BLETypes.h | 40 ++++++++++--------- .../source/generic/GenericSecurityManager.cpp | 4 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 1fbde5df4d..8095345657 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -261,6 +261,27 @@ private: uint8_t ascii[PASSKEY_LEN]; }; +/** + * Returns true if every byte is equal to zero + */ +template +bool is_all_zeros(byte_array_class &byte_array) { + for (size_t i = 0; i < byte_array.size(); i++) { + if (byte_array[i] != 0) { + return false; + } + } + return true; +} + +/** + * Zero out all bytes + */ +template +void set_all_zeros(byte_array_class &byte_array) { + memset(&byte_array[0], 0x00, byte_array.size()); +} + template struct byte_array_t { /** @@ -324,25 +345,6 @@ struct byte_array_t { return _value; } - /** - * Returns true if every byte is equal to zero - */ - bool is_all_zeros() { - for (size_t i = 0; i < array_size; i++) { - if (_value[i] != 0) { - return false; - } - } - return true; - } - - /** - * Zero out all bytes - */ - void set_all_zeros() { - memset(_value, 0x00, array_size); - } - /** * Size in byte of a data. */ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index f93b9efa6e..2d9da8a0a9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -525,14 +525,14 @@ ble_error_t GenericSecurityManager::generateOOB( /* Secure connections. Avoid generating if we're already waiting for it. * If a local random is set to 0 it means we're already calculating. */ - if (!_oob_local_random.is_all_zeros()) { + if (!is_all_zeros(_oob_local_random)) { status = _pal.generate_secure_connections_oob(); if (status == BLE_ERROR_NONE) { _oob_local_address = *address; /* this will be updated when calculation completes, * a value of all zeros is an invalid random value */ - _oob_local_random.set_all_zeros(); + set_all_zeros(_oob_local_random); } else if (status != BLE_ERROR_NOT_IMPLEMENTED) { return status; } From 26b047549c87a50fa10934c3c63b915b47c6dfbb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 15:17:15 +0100 Subject: [PATCH 053/274] extra comments for api --- features/FEATURE_BLE/ble/SecurityManager.h | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 139e61b68d..11294a7461 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -738,7 +738,12 @@ public: /** * Generate OOB data with the given address. If Secure Connections is supported this will * also generate Secure Connections OOB data on top of legacy pairing OOB data. This can be used - * to generate such data before any connections take place. + * to generate such data before the connection takes place. + * + * In this model the OOB exchange takes place before the devices connect. Devices should establish + * communication over another channel and exchange the OOB data. The address provided will be used + * by the peer to associate the received data with the address of the device it will then connect + * to over BLE. * * @param[in] address The local address you will use in the connection using this OOB data. This * address will be returned along with the rest of the OOB data when generation @@ -755,11 +760,23 @@ public: * Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will * generate Secure Connections OOB data through oobGenerated() on top of legacy pairing OOB data. * + * You do not have to call this function to return received OOB data. Use legacyPairingOobReceived + * or oobReceived to hand it in. This will allow the stack to use it if possible. You only need to + * call this function to attempt legacy OOB data exchange after pairing start and to inform + * the stack OOB data does not provide MITM protection (by default it is set to provide this). + * + * In this model the OOB exchange takes places after the devices have connected but possibly + * prior to pairing. For secure connections pairing must not be started until after the OOB + * data has been sent and/or received. The address in the OOB data generated will match + * the original address used to establish the connection and will be used by the peer to + * identify which connection the OOB data belongs to. + * * @param[in] connectionHandle Handle to identify the connection. * @param[in] useOOB If set to true, authenticate using OOB data. * @param[in] OOBProvidesMITM If set to true keys exchanged during pairing using OOB data - * will provide MITM protection. This indicates that the form - * of exchange used by the OOB data itself provides MITM protection. + * will provide Man-in-the-Middle protection. This indicates that + * the form of exchange used by the OOB data itself provides MITM + * protection. * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. */ virtual ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true) { From 576796b28979f23d22a498316e330b28f5388ba6 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 15:29:26 +0100 Subject: [PATCH 054/274] reset OOB on use --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 2d9da8a0a9..1178e5afe9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -1032,6 +1032,8 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle if (cb->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); } else { _pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE); } @@ -1049,6 +1051,11 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c 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) { + set_all_zeros(_oob_temporary_key_creator_address); + } + } else if (!cb->legacy_pairing_oob_request_pending) { cb->legacy_pairing_oob_request_pending = true; From 5ae9cc3b53e02b9a8e71e141536b6c9990f9e1ca Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 28 Mar 2018 18:30:01 +0100 Subject: [PATCH 055/274] set peer csrk on pal --- features/FEATURE_BLE/ble/GattClient.h | 9 ++++ .../ble/generic/GenericSecurityManager.h | 13 +++++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 12 +++++ .../source/generic/GenericGattClient.cpp | 23 ++++++++-- .../source/generic/GenericSecurityManager.cpp | 45 ++++++++++++++++--- .../TARGET_CORDIO/CordioPalSecurityManager.h | 8 ++++ .../source/CordioPalSecurityManager.cpp | 8 ++++ 7 files changed, 108 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattClient.h b/features/FEATURE_BLE/ble/GattClient.h index 137304bc23..cabfaf9a19 100644 --- a/features/FEATURE_BLE/ble/GattClient.h +++ b/features/FEATURE_BLE/ble/GattClient.h @@ -116,6 +116,15 @@ public: * The server does not acknowledge the status of the operation. */ GATT_OP_WRITE_CMD = 0x02, + + /** + * Signed Write command. + * + * It is used to request the server to write the value of an attribute + * using a signed packet. The server does not acknowledge the status + * of the operation. + */ + GATT_OP_SIGNED_WRITE_CMD = 0x03 }; /** diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 1b16a548fa..b55bd7cc11 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -322,13 +322,24 @@ private: * Returns the CSRK for the connection. Called by the security db. * * @param[in] connectionHandle Handle to identify the connection. - * @param[in] entryKeys security entry containing keys. + * @param[in] csrk connection signature resolving key. */ void return_csrk_cb( pal::SecurityDb::entry_handle_t connection, const csrk_t *csrk ); + /** + * 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. + */ + void set_peer_csrk_cb( + pal::SecurityDb::entry_handle_t connection, + const csrk_t *csrk + ); + /** * Updates the entry for the connection with OOB data presence. * diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 1833c8bda5..8341a1ab3b 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -865,6 +865,18 @@ public: const csrk_t &csrk ) = 0; + /** + * Set the peer CSRK for particular connection. + * + * @param[in] connection connection handle + * @param[in] csrk signing key + * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk + ) = 0; + //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 97c6d57fc0..2309d7a79a 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -21,6 +21,8 @@ #include #include "ble/generic/GenericGattClient.h" #include "ble/blecommon.h" +#include "ble/BLEInstanceBase.h" +#include "ble/generic/GenericSecurityManager.h" #include using ble::pal::AttServerMessage; @@ -1062,6 +1064,11 @@ ble_error_t GenericGattClient::read( return err; } +#define PREPARE_WRITE_HEADER_LENGTH 5 +#define WRITE_HEADER_LENGTH 3 +#define CMAC_LENGTH 8 +#define MAC_COUNTER_LENGTH 4 + ble_error_t GenericGattClient::write( GattClient::WriteOp_t cmd, Gap::Handle_t connection_handle, @@ -1077,7 +1084,7 @@ ble_error_t GenericGattClient::write( uint16_t mtu = get_mtu(connection_handle); if (cmd == GattClient::GATT_OP_WRITE_CMD) { - if (length > (uint16_t)(mtu - 3)) { + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } return _pal_client->write_without_response( @@ -1085,10 +1092,20 @@ ble_error_t GenericGattClient::write( attribute_handle, make_const_ArrayView(value, length) ); + } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->signed_write_without_response( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); } else { uint8_t* data = NULL; - if (length > (uint16_t)(mtu - 3)) { + if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { data = (uint8_t*) malloc(length); if (data == NULL) { return BLE_ERROR_NO_MEM; @@ -1115,7 +1132,7 @@ ble_error_t GenericGattClient::write( err = _pal_client->queue_prepare_write( connection_handle, attribute_handle, - make_const_ArrayView(value, mtu - 5), + make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), /* offset */ 0 ); } else { diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 1178e5afe9..ead0cc0b4c 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -313,17 +313,27 @@ ble_error_t GenericSecurityManager::enableSigning( } cb->signing_requested = enabled; - cb->signing_override_default = false; + cb->signing_override_default = true; if (cb->encrypted) { return BLE_ERROR_INVALID_STATE; } - if (!cb->csrk_stored && cb->signing_requested) { - init_signing(); - if (cb->is_master) { - return requestPairing(connection); + + if (cb->signing_requested) { + if (cb->csrk_stored) { + /* used the stored ones when available */ + _db.get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); } else { - return slave_security_request(connection); + /* crate keys if needed and exchange them */ + init_signing(); + if (cb->is_master) { + return requestPairing(connection); + } else { + return slave_security_request(connection); + } } } @@ -729,6 +739,18 @@ void GenericSecurityManager::set_ltk_cb( } } +void GenericSecurityManager::set_peer_csrk_cb( + pal::SecurityDb::entry_handle_t db_entry, + const csrk_t *csrk +) { + ControlBlock_t *cb = get_control_block(db_entry); + if (!cb) { + return; + } + + _pal.set_peer_csrk(cb->connection, *csrk); +} + void GenericSecurityManager::return_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, const csrk_t *csrk @@ -808,6 +830,17 @@ void GenericSecurityManager::on_connected( if (dist_flags) { *static_cast(cb) = *dist_flags; } + + const bool signing = cb->signing_override_default ? + cb->signing_requested + : _default_key_distribution.get_signing(); + + if (signing && cb->csrk_stored) { + _db.get_entry_peer_csrk( + mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb), + cb->db_entry + ); + } } void GenericSecurityManager::on_disconnected( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index b04788f31f..38b41ca74c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -239,6 +239,14 @@ public: */ virtual ble_error_t set_csrk(const csrk_t &csrk); + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk + ); + //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index bff6eef611..1c54f60301 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -272,6 +272,14 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) return BLE_ERROR_NONE; } +ble_error_t CordioSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk +) { + /* TODO implement */ + return BLE_ERROR_NOT_IMPLEMENTED; +} + //////////////////////////////////////////////////////////////////////////// // Global parameters // From 8d966dbe8caa3d3ebb0d0630c70a5f787500652f Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 13:46:26 +0100 Subject: [PATCH 056/274] invalid mic event --- .../FEATURE_BLE/ble/generic/GenericSecurityManager.h | 6 ++++++ features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 10 ++++++++++ .../source/generic/GenericSecurityManager.cpp | 5 +++++ 3 files changed, 21 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index b55bd7cc11..a8a82a7a77 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -524,6 +524,12 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_invalid_mic + */ + virtual void on_invalid_mic( + connection_handle_t connection + ); + /** @copydoc ble::pal::SecurityManager::on_slave_security_request */ virtual void on_slave_security_request( diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 8341a1ab3b..ce2063e46e 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -280,6 +280,16 @@ public: connection_handle_t connection ) = 0; + /** + * Indicate that the MIC verification has failed. This could + * be due to an invalid CSRK key. + * + * @param[in] connection connection handle + */ + virtual void on_invalid_mic( + connection_handle_t connection + ) = 0; + /** * Ask the stack to evaluate the security request received from the slave. * This might result in the stack enabling encryption, or pairing/re-pairing. diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index ead0cc0b4c..43cccfc6e9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -945,6 +945,11 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } +void GenericSecurityManager::on_invalid_mic(connection_handle_t connection) { + (void)connection; + /* TODO: count and re-pair when threshold reached */ +} + void GenericSecurityManager::on_slave_security_request( connection_handle_t connection, AuthenticationMask authentication From 511135f31ccceb8f5c819fbd83e7b19a3b2077cc Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 13:47:22 +0100 Subject: [PATCH 057/274] signing only for the slave, unless keys requested to be sent by master --- .../source/generic/GenericSecurityManager.cpp | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 43cccfc6e9..e0974bcc90 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -140,14 +140,10 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio * use when roles are changed */ if (_master_sends_keys) { initiator_distribution = _default_key_distribution; - } - - /* override default if requested */ - if (cb->signing_override_default) { - initiator_distribution.set_signing(cb->signing_requested); - } else { - /* because _master_sends_keys might be false so we need to set this */ - initiator_distribution.set_signing(_default_key_distribution.get_signing()); + /* override default if requested */ + if (cb->signing_override_default) { + initiator_distribution.set_signing(cb->signing_requested); + } } KeyDistribution responder_distribution(_default_key_distribution); @@ -312,14 +308,10 @@ ble_error_t GenericSecurityManager::enableSigning( return BLE_ERROR_INVALID_PARAM; } - cb->signing_requested = enabled; cb->signing_override_default = true; - if (cb->encrypted) { - return BLE_ERROR_INVALID_STATE; - } - - if (cb->signing_requested) { + if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) { + cb->signing_requested = true; if (cb->csrk_stored) { /* used the stored ones when available */ _db.get_entry_peer_csrk( @@ -335,6 +327,8 @@ ble_error_t GenericSecurityManager::enableSigning( return slave_security_request(connection); } } + } else { + cb->signing_requested = enabled; } return BLE_ERROR_NONE; From 780d8a43751a916e9b3e27efdd2816a065b09cc7 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:24:40 +0100 Subject: [PATCH 058/274] let the stack know whether csrk is authenticated --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 3 ++- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 5 ++++- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 3 ++- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index ce2063e46e..dcdc194e51 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -884,7 +884,8 @@ public: */ virtual ble_error_t set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ) = 0; //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index e0974bcc90..3f5bf678f2 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -742,7 +742,10 @@ void GenericSecurityManager::set_peer_csrk_cb( return; } - _pal.set_peer_csrk(cb->connection, *csrk); + _pal.set_peer_csrk( + cb->connection, + *csrk, + cb->csrk_mitm_protected); } void GenericSecurityManager::return_csrk_cb( diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 38b41ca74c..fe5da7d159 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -244,7 +244,8 @@ public: */ virtual ble_error_t set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ); //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 1c54f60301..5a02ea0e8c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -274,7 +274,8 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) ble_error_t CordioSecurityManager::set_peer_csrk( connection_handle_t connection, - const csrk_t &csrk + const csrk_t &csrk, + bool authenticated ) { /* TODO implement */ return BLE_ERROR_NOT_IMPLEMENTED; From 9283413c4c9327196f03f0716a2948ef954ba0c8 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:44:15 +0100 Subject: [PATCH 059/274] count failures, trigger reparing when verification fails --- .../ble/generic/GenericSecurityManager.h | 4 +++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 4 ++-- .../source/generic/GenericSecurityManager.cpp | 21 +++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index a8a82a7a77..211e97ad6a 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -454,6 +454,8 @@ private: uint8_t oob_mitm_protection:1; uint8_t oob_present:1; uint8_t legacy_pairing_oob_request_pending:1; + + uint8_t mic_failures:2; }; pal::SecurityManager &_pal; @@ -526,7 +528,7 @@ public: /** @copydoc ble::pal::SecurityManager::on_invalid_mic */ - virtual void on_invalid_mic( + virtual void on_signature_verification_failure( connection_handle_t connection ); diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index dcdc194e51..9b98f8e3b7 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -281,12 +281,12 @@ public: ) = 0; /** - * Indicate that the MIC verification has failed. This could + * Indicate that signed data was rejected due to verification failure. This could * be due to an invalid CSRK key. * * @param[in] connection connection handle */ - virtual void on_invalid_mic( + virtual void on_signature_verification_failure( connection_handle_t connection ) = 0; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 3f5bf678f2..801569e4a3 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -942,9 +942,21 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } -void GenericSecurityManager::on_invalid_mic(connection_handle_t connection) { - (void)connection; - /* TODO: count and re-pair when threshold reached */ +void GenericSecurityManager::on_signature_verification_failure(connection_handle_t connection) { + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + + cb->mic_failures++; + if (cb->mic_failures == 3) { + cb->mic_failures = 0; + if (cb->is_master) { + requestPairing(connection); + } else { + slave_security_request(connection); + } + } } void GenericSecurityManager::on_slave_security_request( @@ -1263,7 +1275,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : attempt_oob(false), oob_mitm_protection(false), oob_present(false), - legacy_pairing_oob_request_pending(false) { } + legacy_pairing_oob_request_pending(false), + mic_failures(0) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { From f5fee68f99f5c0e9e18c78a69a3b3bf5ab7528f8 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 15:47:50 +0100 Subject: [PATCH 060/274] fixed naming for sig failure count --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 2 +- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 211e97ad6a..c2f0b28f85 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -455,7 +455,7 @@ private: uint8_t oob_present:1; uint8_t legacy_pairing_oob_request_pending:1; - uint8_t mic_failures:2; + uint8_t csrk_failures:2; }; pal::SecurityManager &_pal; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 801569e4a3..666a6ec992 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -948,9 +948,9 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle return; } - cb->mic_failures++; - if (cb->mic_failures == 3) { - cb->mic_failures = 0; + cb->csrk_failures++; + if (cb->csrk_failures == 3) { + cb->csrk_failures = 0; if (cb->is_master) { requestPairing(connection); } else { @@ -1276,7 +1276,7 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() : oob_mitm_protection(false), oob_present(false), legacy_pairing_oob_request_pending(false), - mic_failures(0) { } + csrk_failures(0) { } void GenericSecurityManager::on_ltk_request(connection_handle_t connection) { From e276478d58002c1483e88bcf02bcb91f882ab2f8 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:02:27 +0100 Subject: [PATCH 061/274] only bother reacting to verification failures if we want to use signing --- .../source/generic/GenericSecurityManager.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 666a6ec992..c3bdf90113 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -948,13 +948,19 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle return; } - cb->csrk_failures++; - if (cb->csrk_failures == 3) { - cb->csrk_failures = 0; - if (cb->is_master) { - requestPairing(connection); - } else { - slave_security_request(connection); + const bool signing = cb->signing_override_default ? + cb->signing_requested + : _default_key_distribution.get_signing(); + + if (signing) { + cb->csrk_failures++; + if (cb->csrk_failures == 3) { + cb->csrk_failures = 0; + if (cb->is_master) { + requestPairing(connection); + } else { + slave_security_request(connection); + } } } } From dfdfcfb25ea13e96625a98443737c2233baaa9d3 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:24:20 +0100 Subject: [PATCH 062/274] style fix --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index c3bdf90113..c3a9aedbf4 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -942,7 +942,9 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection (void)connection; } -void GenericSecurityManager::on_signature_verification_failure(connection_handle_t connection) { +void GenericSecurityManager::on_signature_verification_failure( + connection_handle_t connection +) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { return; @@ -957,9 +959,9 @@ void GenericSecurityManager::on_signature_verification_failure(connection_handle if (cb->csrk_failures == 3) { cb->csrk_failures = 0; if (cb->is_master) { - requestPairing(connection); + requestPairing(connection); } else { - slave_security_request(connection); + slave_security_request(connection); } } } From 15c06acfe4b500fb9c1a16ccec3cc674edff7cb3 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:53:54 +0100 Subject: [PATCH 063/274] style fix --- .../source/generic/GenericGattClient.cpp | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 2309d7a79a..759b707444 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1081,20 +1081,19 @@ ble_error_t GenericGattClient::write( return BLE_ERROR_INVALID_STATE; } - uint16_t mtu = get_mtu(connection_handle); + uint16_t mtu = get_mtu(connection_handle); - if (cmd == GattClient::GATT_OP_WRITE_CMD) { - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - return _pal_client->write_without_response( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { - - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { + if (cmd == GattClient::GATT_OP_WRITE_CMD) { + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; + } + return _pal_client->write_without_response( + connection_handle, + attribute_handle, + ); + } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + /*TODO check encryption status */ + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } return _pal_client->signed_write_without_response( @@ -1102,56 +1101,56 @@ ble_error_t GenericGattClient::write( attribute_handle, make_const_ArrayView(value, length) ); - } else { - uint8_t* data = NULL; + } else { + uint8_t* data = NULL; - if (length > (uint16_t)(mtu - WRITE_HEADER_LENGTH)) { - data = (uint8_t*) malloc(length); - if (data == NULL) { - return BLE_ERROR_NO_MEM; - } - memcpy(data, value, length); - } + if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { + data = (uint8_t*) malloc(length); + if (data == NULL) { + return BLE_ERROR_NO_MEM; + } + memcpy(data, value, length); + } - WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock( - connection_handle, - attribute_handle, - data, - length - ); + WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock( + connection_handle, + attribute_handle, + data, + length + ); - if (write_pcb == NULL) { - free(data); - return BLE_ERROR_NO_MEM; - } + if (write_pcb == NULL) { + free(data); + return BLE_ERROR_NO_MEM; + } - insert_control_block(write_pcb); + insert_control_block(write_pcb); - ble_error_t err = BLE_ERROR_UNSPECIFIED; - if (data) { - err = _pal_client->queue_prepare_write( - connection_handle, - attribute_handle, - make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), - /* offset */ 0 - ); - } else { - err = _pal_client->write_attribute( - connection_handle, - attribute_handle, - make_const_ArrayView(value, length) - ); - } + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (data) { + err = _pal_client->queue_prepare_write( + connection_handle, + attribute_handle, + make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH), + /* offset */0 + ); + } else { + err = _pal_client->write_attribute( + connection_handle, + attribute_handle, + make_const_ArrayView(value, length) + ); + } - if (err) { - remove_control_block(write_pcb); - delete write_pcb; - } + if (err) { + remove_control_block(write_pcb); + delete write_pcb; + } - return err; - } + return err; + } - return BLE_ERROR_NOT_IMPLEMENTED; + return BLE_ERROR_NOT_IMPLEMENTED; } void GenericGattClient::onServiceDiscoveryTermination( From c1e2e07241ad5a7840f67f204bbfb77a9f390d98 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 29 Mar 2018 16:56:32 +0100 Subject: [PATCH 064/274] missing line from commit (github client fail) --- features/FEATURE_BLE/source/generic/GenericGattClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 759b707444..a6d1d0692e 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1090,6 +1090,7 @@ ble_error_t GenericGattClient::write( return _pal_client->write_without_response( connection_handle, attribute_handle, + make_const_ArrayView(value, length) ); } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { /*TODO check encryption status */ From cbf80e9da56802c3e7684b11f6caa34f89ab9d6c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 3 Apr 2018 09:57:58 +0100 Subject: [PATCH 065/274] typos, style and other review fixes --- .../ble/generic/GenericSecurityManager.h | 2 +- .../source/generic/GenericGattClient.cpp | 10 +++++----- .../source/generic/GenericSecurityManager.cpp | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index c2f0b28f85..7fe92b3b30 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -526,7 +526,7 @@ public: connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_invalid_mic + /** @copydoc ble::pal::SecurityManager::on_signature_verification_failure */ virtual void on_signature_verification_failure( connection_handle_t connection diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index a6d1d0692e..4962b9dd2b 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -40,6 +40,11 @@ using ble::pal::AttHandleValueIndication; using ble::pal::AttHandleValueNotification; using ble::pal::AttFindInformationResponse; +#define PREPARE_WRITE_HEADER_LENGTH 5 +#define WRITE_HEADER_LENGTH 3 +#define CMAC_LENGTH 8 +#define MAC_COUNTER_LENGTH 4 + namespace ble { namespace generic { @@ -1064,11 +1069,6 @@ ble_error_t GenericGattClient::read( return err; } -#define PREPARE_WRITE_HEADER_LENGTH 5 -#define WRITE_HEADER_LENGTH 3 -#define CMAC_LENGTH 8 -#define MAC_COUNTER_LENGTH 4 - ble_error_t GenericGattClient::write( GattClient::WriteOp_t cmd, Gap::Handle_t connection_handle, diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index c3a9aedbf4..a079c58c68 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -319,7 +319,7 @@ ble_error_t GenericSecurityManager::enableSigning( cb->db_entry ); } else { - /* crate keys if needed and exchange them */ + /* create keys if needed and exchange them */ init_signing(); if (cb->is_master) { return requestPairing(connection); @@ -745,7 +745,8 @@ void GenericSecurityManager::set_peer_csrk_cb( _pal.set_peer_csrk( cb->connection, *csrk, - cb->csrk_mitm_protected); + cb->csrk_mitm_protected + ); } void GenericSecurityManager::return_csrk_cb( @@ -829,8 +830,8 @@ void GenericSecurityManager::on_connected( } const bool signing = cb->signing_override_default ? - cb->signing_requested - : _default_key_distribution.get_signing(); + cb->signing_requested : + _default_key_distribution.get_signing(); if (signing && cb->csrk_stored) { _db.get_entry_peer_csrk( @@ -951,8 +952,8 @@ void GenericSecurityManager::on_signature_verification_failure( } const bool signing = cb->signing_override_default ? - cb->signing_requested - : _default_key_distribution.get_signing(); + cb->signing_requested : + _default_key_distribution.get_signing(); if (signing) { cb->csrk_failures++; From 7bf0eb009a4384556a72d636c161b7e6420692e5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 11:04:13 +0100 Subject: [PATCH 066/274] BLE: use ArrayView to pass and get parameters in Crypto API This change allow vendor pal code to use its own array format. --- .../TARGET_NRF5/source/nRF5XCrypto.cpp | 42 +++++++++++-------- .../TARGET_NRF5/source/nRF5xCrypto.h | 21 +++++----- .../source/nRF5xPalSecurityManager.cpp | 18 ++++---- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp index 9c6cb00232..7e4c0de9d0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -20,6 +20,7 @@ #include "ble/BLETypes.h" #include "cmsis.h" #include "nRF5xCrypto.h" +#include "platform/mbed_assert.h" namespace ble { namespace pal { @@ -42,10 +43,14 @@ LescCrypto::~LescCrypto() { } bool LescCrypto::generate_keys( - ble::public_key_coord_t& X, - ble::public_key_coord_t& Y, - ble::public_key_coord_t& secret + ArrayView X, + ArrayView Y, + ArrayView secret ) { + MBED_ASSERT(X.size() == public_key_coord_t::size()); + MBED_ASSERT(Y.size() == public_key_coord_t::size()); + MBED_ASSERT(secret.size() == public_key_coord_t::size()); + mbedtls_mpi secret_key; mbedtls_ecp_point public_keys; @@ -73,11 +78,16 @@ bool LescCrypto::generate_keys( } bool LescCrypto::generate_shared_secret( - const ble::public_key_coord_t& peer_X, - const ble::public_key_coord_t& peer_Y, - const ble::public_key_coord_t& own_secret, - ble::public_key_coord_t& shared_secret + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret ) { + MBED_ASSERT(peer_X.size() == public_key_coord_t::size()); + MBED_ASSERT(peer_Y.size() == public_key_coord_t::size()); + MBED_ASSERT(own_secret.size() == public_key_coord_t::size()); + MBED_ASSERT(shared_secret.size() == dhkey_t::size()); + mbedtls_mpi result; mbedtls_mpi secret_key; mbedtls_ecp_point public_keys; @@ -112,19 +122,15 @@ bool LescCrypto::generate_shared_secret( } -void LescCrypto::load_mpi(mbedtls_mpi& dest, const ble::public_key_coord_t& src) { - ble::public_key_coord_t src_be = src; - swap_endian(src_be); - mbedtls_mpi_read_binary(&dest, src_be.buffer(), src_be.size()); +void LescCrypto::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { + ble::public_key_coord_t src_be = src.data(); + swap_endian(src_be.buffer(), src_be.size()); + mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); } -void LescCrypto::store_mpi(ble::public_key_coord_t& dest, const mbedtls_mpi& src) { - mbedtls_mpi_write_binary(&src, dest.buffer(), dest.size()); - swap_endian(dest); -} - -void LescCrypto::swap_endian(ble::public_key_coord_t& to_swap) { - swap_endian(to_swap.buffer(), to_swap.size()); +void LescCrypto::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { + mbedtls_mpi_write_binary(&src, dest.data(), dest.size()); + swap_endian(dest.data(), dest.size()); } void LescCrypto::swap_endian(uint8_t* buf, size_t len) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index 1478d4213f..afbb37b898 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -22,6 +22,7 @@ #include "platform/CriticalSectionLock.h" #include "ble/BLETypes.h" #include "cmsis.h" +#include "ble/ArrayView.h" namespace ble { namespace pal { @@ -36,25 +37,25 @@ public: ~LescCrypto(); bool generate_keys( - ble::public_key_coord_t& X, - ble::public_key_coord_t& Y, - ble::public_key_coord_t& secret + ArrayView X, + ArrayView Y, + ArrayView secret ); bool generate_shared_secret( - const ble::public_key_coord_t& peer_X, - const ble::public_key_coord_t& peer_Y, - const ble::public_key_coord_t& own_secret, - ble::public_key_coord_t& shared_secret + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret ); private: - void load_mpi(mbedtls_mpi& dest, const ble::public_key_coord_t& src); + void load_mpi(mbedtls_mpi& dest, const ArrayView& src); - void store_mpi(ble::public_key_coord_t& dest, const mbedtls_mpi& src); + void store_mpi(ArrayView& dest, const mbedtls_mpi& src); - void swap_endian(ble::public_key_coord_t& to_swap); + void swap_endian(ArrayView& to_swap); void swap_endian(uint8_t* buf, size_t len); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index cce5cf1d83..e6f00eccc5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -104,7 +104,11 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { - if (_crypto.generate_keys(X, Y, secret)) { + if (_crypto.generate_keys( + make_ArrayView(X.buffer(), X.size()), + make_ArrayView(Y.buffer(), Y.size()), + make_ArrayView(secret.buffer(), secret.size()) + )) { return BLE_ERROR_NONE; } @@ -797,19 +801,15 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) gap_evt.params.lesc_dhkey_request; size_t key_size = public_key_coord_t::size(); - public_key_coord_t peer_X(dhkey_request.p_pk_peer->pk, key_size); - public_key_coord_t peer_Y(dhkey_request.p_pk_peer->pk + key_size, key_size); - public_key_coord_t sh_secret; ble_gap_lesc_dhkey_t shared_secret; _crypto.generate_shared_secret( - peer_X, - peer_Y, - self.secret, - sh_secret + make_const_ArrayView(dhkey_request.p_pk_peer->pk, key_size), + make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size, key_size), + make_const_ArrayView(secret.data(), secret.size()), + shared_secret.key ); - memcpy(shared_secret.key, sh_secret.data(), sh_secret.size()); sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret); if (dhkey_request.oobd_req) { From bf41bb3164084fed4988ef043ddcc3c30a97ce5a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:21:05 +0100 Subject: [PATCH 067/274] BLE: Export byte_array_t size exploitable at compile time. --- features/FEATURE_BLE/ble/BLETypes.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index dbeadfe316..5dba99796c 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -263,6 +263,11 @@ private: template struct byte_array_t { + /** + * Size of the array; accessible at compile time. + */ + static const size_t size_ = array_size; + /** * Default to all zeroes */ From d8f3d9c5eff76358229a2d11028a4ebdf1a90af5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:21:54 +0100 Subject: [PATCH 068/274] BLE: provide non const overload of byte_array_t::data member function. --- features/FEATURE_BLE/ble/BLETypes.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 5dba99796c..f5f13a84df 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -329,6 +329,14 @@ struct byte_array_t { return _value; } + /** + * Return the pointer to the buffer holding data. + */ + uint8_t* data() { + return _value; + } + + /** * Return the pointer to the buffer holding data. */ From 9e1f0b34f8e69994582fa97140bac73029217f1f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:22:15 +0100 Subject: [PATCH 069/274] BLE: Fix byte_array_t subscript operator --- features/FEATURE_BLE/ble/BLETypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index f5f13a84df..5f20c232a4 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -311,14 +311,14 @@ struct byte_array_t { /** * Subscript operator to access data content */ - uint8_t& operator[](uint8_t i) { + uint8_t& operator[](size_t i) { return _value[i]; } /** * Subscript operator to access data content */ - uint8_t operator[](uint8_t i) const { + uint8_t operator[](size_t i) const { return _value[i]; } From 5761caff00f8791068bdc9a932d51547850c8cf0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:28:17 +0100 Subject: [PATCH 070/274] BLE: Extend ArrayView to encode size in type. With this change, it is possible to encode the size of the array viewed by an ArrayView into the type itself: ArrayView. Such objects are lighter than ArrayView of arbitrary size and allows verification of the size at compile time. This change also fix operator== and bring new make_ArrayView overloads. --- features/FEATURE_BLE/ble/ArrayView.h | 241 +++++++++++++++++++++++---- 1 file changed, 206 insertions(+), 35 deletions(-) diff --git a/features/FEATURE_BLE/ble/ArrayView.h b/features/FEATURE_BLE/ble/ArrayView.h index d2a2b6d135..fad829eba1 100644 --- a/features/FEATURE_BLE/ble/ArrayView.h +++ b/features/FEATURE_BLE/ble/ArrayView.h @@ -17,8 +17,11 @@ #ifndef BLE_ARRAY_VIEW_H_ #define BLE_ARRAY_VIEW_H_ +#include + #include #include +#include "platform/mbed_assert.h" /** * @addtogroup ble @@ -33,11 +36,18 @@ namespace ble { +/** + * Special value for the Size parameter of ArrayView. + * If the type use this value then the size of the array is stored in the object + * at runtime. + */ +#define ARRAY_VIEW_DYNAMIC_SIZE -1 + /** * Immutable view to an array. * * Array views encapsulate the pointer to an array and its size into a single - * object; however, it does not manage the lifetime of the array viewed. + * object or type; however, it does not manage the lifetime of the array viewed. * You can use instances of ArrayView to replace the traditional pair of pointer * and size arguments in function calls. * @@ -48,20 +58,28 @@ namespace ble { * @note You can create ArrayView instances with the help of the function * template make_ArrayView() and make_const_ArrayView(). * + * @note ArrayView objects can be implicitly converted to ArrayView + * objects where required. + * * @tparam T type of objects held by the array. + * @tparam Size The size of the array viewed. The default value + * ARRAY_VIEW_DYNAMIC_SIZE is special as it allows construction of ArrayView + * objects of any size (set at runtime). */ -template +template struct ArrayView { + MBED_STATIC_ASSERT(Size >= 0, "Invalid size for an ArrayView"); + /** * Construct a view to an empty array. * * @post a call to size() will return 0, and data() will return NULL. */ - ArrayView() : _array(0), _size(0) { } + ArrayView() : _array(NULL) { } /** - * Construct an array view from a pointer to a buffer and its size. + * Construct an array view from a pointer to a buffer. * * @param array_ptr Pointer to the array data * @param array_size Number of elements of T present in the array. @@ -70,7 +88,9 @@ struct ArrayView { * array_tpr. */ ArrayView(T* array_ptr, size_t array_size) : - _array(array_ptr), _size(array_size) { } + _array(array_ptr) { + MBED_ASSERT(array_size >= (size_t) Size); + } /** * Construct an array view from the reference to an array. @@ -82,9 +102,8 @@ struct ArrayView { * @post a call to size() will return Size, and data() will return * a pointer to elements. */ - template ArrayView(T (&elements)[Size]): - _array(elements), _size(Size) { } + _array(elements) { } /** * Return the size of the array viewed. @@ -93,7 +112,7 @@ struct ArrayView { */ size_t size() const { - return _size; + return _array ? Size : 0; } /** @@ -144,40 +163,115 @@ struct ArrayView { return _array; } +private: + T* const _array; +}; + +/** + * ArrayView specialisation that handle dynamic array size. + */ +template +struct ArrayView { + /** - * Equality operator. + * Construct a view to an empty array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. - * - * @return True if arrays in input have the same size and the same content - * and false otherwise. + * @post a call to size() will return 0, and data() will return NULL. */ - friend bool operator==(const ArrayView& lhs, const ArrayView& rhs) + ArrayView() : _array(0), _size(0) { } + + /** + * Construct an array view from a pointer to a buffer and its size. + * + * @param array_ptr Pointer to the array data + * @param array_size Number of elements of T present in the array. + * + * @post a call to size() will return array_size and data() will return + * array_tpr. + */ + ArrayView(T* array_ptr, size_t array_size) : + _array(array_ptr), _size(array_size) { } + + /** + * Construct an array view from the reference to an array. + * + * @param elements Reference to the array viewed. + * + * @tparam Size Number of elements of T presents in the array. + * + * @post a call to size() will return Size, and data() will return + * a pointer to elements. + */ + template + ArrayView(T (&elements)[Size]): + _array(elements), _size(Size) { } + + + /** + * Construct a ArrayView object with a dynamic size from an ArrayView object + * with a static size. + * @param other The ArrayView object used to construct this. + */ + template + ArrayView(ArrayView other): + _array(other.data()), _size(other.size()) { } + + /** + * Return the size of the array viewed. + * + * @return The number of elements present in the array viewed. + */ + size_t size() const { - if (lhs.size() != rhs.size()) { - return false; - } - - if (lhs.data() == rhs.data()) { - return true; - } - - return memcmp(lhs.data(), rhs.data(), lhs.size()) == 0; + return _size; } /** - * Not equal operator + * Access to a mutable element of the array. * - * @param lhs Left hand side of the binary operation. - * @param rhs Right hand side of the binary operation. + * @param index Element index to access. * - * @return True if arrays in input do not have the same size or the same - * content and false otherwise. + * @return A reference to the element at the index specified in input. + * + * @pre index shall be less than size(). */ - friend bool operator!=(const ArrayView& lhs, const ArrayView& rhs) + T& operator[](size_t index) { - return !(lhs == rhs); + return _array[index]; + } + + /** + * Access to an immutable element of the array. + * + * @param index Element index to access. + * + * @return A const reference to the element at the index specified in input. + * + * @pre index shall be less than size(). + */ + const T& operator[](size_t index) const + { + return _array[index]; + } + + /** + * Get the raw pointer to the array. + * + * @return The raw pointer to the array. + */ + T* data() + { + return _array; + } + + /** + * Get the raw const pointer to the array. + * + * @return The raw pointer to the array. + */ + const T* data() const + { + return _array; } private: @@ -186,6 +280,45 @@ private: }; +/** + * Equality operator. + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input have the same size and the same content + * and false otherwise. + */ +template +bool operator==(const ArrayView& lhs, const ArrayView& rhs) +{ + if (lhs.size() != rhs.size()) { + return false; + } + + if (lhs.data() == rhs.data()) { + return true; + } + + return std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data()); +} + +/** + * Not equal operator + * + * @param lhs Left hand side of the binary operation. + * @param rhs Right hand side of the binary operation. + * + * @return True if arrays in input do not have the same size or the same + * content and false otherwise. + */ +template +bool operator!=(const ArrayView& lhs, const ArrayView& rhs) +{ + return !(lhs == rhs); +} + + /** * Generate an array view from a reference to a C/C++ array. * @@ -200,9 +333,28 @@ private: * created 'inline'. */ template -ArrayView make_ArrayView(T (&elements)[Size]) +ArrayView make_ArrayView(T (&elements)[Size]) { - return ArrayView(elements); + return ArrayView(elements); +} + +/** + * Generate an array view from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The ArrayView to elements. + * + * @note This helper avoids the typing of template parameter when ArrayView is + * created 'inline'. + */ +template +ArrayView make_ArrayView(T* elements) +{ + return ArrayView(elements, Size); } /** @@ -237,9 +389,28 @@ ArrayView make_ArrayView(T* array_ptr, size_t array_size) * created 'inline'. */ template -ArrayView make_const_ArrayView(T (&elements)[Size]) +ArrayView make_const_ArrayView(T (&elements)[Size]) { - return ArrayView(elements); + return ArrayView(elements); +} + +/** + * Generate a const array view from a pointer to a C/C++ array. + * + * @tparam Size Number of items held in elements. + * @tparam T Type of elements held in elements. + * + * @param elements The reference to the array viewed. + * + * @return The ArrayView to elements. + * + * @note This helper avoids the typing of template parameter when ArrayView is + * created 'inline'. + */ +template +ArrayView make_const_ArrayView(const T* elements) +{ + return ArrayView(elements, Size); } /** From cd39406d2075a463d386887c7e18fa0aa06702fc Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:28:52 +0100 Subject: [PATCH 071/274] BLE: Add conversion function from byte_array_t to ArrayView. --- features/FEATURE_BLE/ble/BLETypes.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 5f20c232a4..bbd6785bc2 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -21,6 +21,7 @@ #include #include #include "ble/SafeEnum.h" +#include "ble/ArrayView.h" /** * @addtogroup ble @@ -355,6 +356,32 @@ protected: uint8_t _value[array_size]; }; +/** + * Construct a fixed size ArrayView from a byte_array_t. + * + * @param src byte_array_t to create a view from. + * + * @return An ArrayView to @p src. + */ +template +ArrayView make_ArrayView(byte_array_t& src) +{ + return ArrayView(src.data(), src.size()); +} + +/** + * Construct a fixed size ArrayView from a const byte_array_t. + * + * @param src byte_array_t to create a view from. + * + * @return An ArrayView to @p src. + */ +template +ArrayView make_const_ArrayView(const byte_array_t& src) +{ + return ArrayView(src.data(), src.size()); +} + /** 128 bit keys used by paired devices */ typedef byte_array_t<16> irk_t; typedef byte_array_t<16> csrk_t; From 59a301a256f6ec915c3c16b75c94c282294f386c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:31:31 +0100 Subject: [PATCH 072/274] BLE: CryptoToolbox enhancement - Rename LescCrypto into CryptoToolbox - Use ArrayView of fixed size as parameters - Add licence --- .../TARGET_NRF5/source/nRF5XCrypto.cpp | 53 +++++++++++-------- .../TARGET_NRF5/source/nRF5xCrypto.h | 45 +++++++++++----- .../source/nRF5xPalSecurityManager.cpp | 14 ++--- .../source/nRF5xPalSecurityManager.h | 2 +- 4 files changed, 69 insertions(+), 45 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp index 7e4c0de9d0..c5a4012de2 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -1,3 +1,19 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 #if !defined(MBEDTLS_CONFIG_FILE) @@ -27,7 +43,7 @@ namespace pal { namespace vendor { namespace nordic { -LescCrypto::LescCrypto() : _initialized(false) { +CryptoToolbox::CryptoToolbox() : _initialized(false) { mbedtls_entropy_init(&_entropy_context); mbedtls_ecp_group_init(&_group); int err = mbedtls_ecp_group_load( @@ -37,20 +53,16 @@ LescCrypto::LescCrypto() : _initialized(false) { _initialized = err ? false : true; } -LescCrypto::~LescCrypto() { +CryptoToolbox::~CryptoToolbox() { mbedtls_ecp_group_free(&_group); mbedtls_entropy_free(&_entropy_context); } -bool LescCrypto::generate_keys( - ArrayView X, - ArrayView Y, - ArrayView secret +bool CryptoToolbox::generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret ) { - MBED_ASSERT(X.size() == public_key_coord_t::size()); - MBED_ASSERT(Y.size() == public_key_coord_t::size()); - MBED_ASSERT(secret.size() == public_key_coord_t::size()); - mbedtls_mpi secret_key; mbedtls_ecp_point public_keys; @@ -77,17 +89,12 @@ bool LescCrypto::generate_keys( return err ? false : true; } -bool LescCrypto::generate_shared_secret( - const ArrayView& peer_X, - const ArrayView& peer_Y, - const ArrayView& own_secret, - ArrayView shared_secret +bool CryptoToolbox::generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret ) { - MBED_ASSERT(peer_X.size() == public_key_coord_t::size()); - MBED_ASSERT(peer_Y.size() == public_key_coord_t::size()); - MBED_ASSERT(own_secret.size() == public_key_coord_t::size()); - MBED_ASSERT(shared_secret.size() == dhkey_t::size()); - mbedtls_mpi result; mbedtls_mpi secret_key; mbedtls_ecp_point public_keys; @@ -122,18 +129,18 @@ bool LescCrypto::generate_shared_secret( } -void LescCrypto::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { +void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { ble::public_key_coord_t src_be = src.data(); swap_endian(src_be.buffer(), src_be.size()); mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); } -void LescCrypto::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { +void CryptoToolbox::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { mbedtls_mpi_write_binary(&src, dest.data(), dest.size()); swap_endian(dest.data(), dest.size()); } -void LescCrypto::swap_endian(uint8_t* buf, size_t len) { +void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { std::swap(buf[low], buf[high]); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index afbb37b898..1d1f432d4f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -1,3 +1,19 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 NRF5X_CRYPTO_ #define NRF5X_CRYPTO_ @@ -29,33 +45,34 @@ namespace pal { namespace vendor { namespace nordic { -class LescCrypto : mbed::NonCopyable { +class CryptoToolbox : mbed::NonCopyable { public: - LescCrypto(); + static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; - ~LescCrypto(); + + CryptoToolbox(); + + ~CryptoToolbox(); bool generate_keys( - ArrayView X, - ArrayView Y, - ArrayView secret + ArrayView X, + ArrayView Y, + ArrayView secret ); bool generate_shared_secret( - const ArrayView& peer_X, - const ArrayView& peer_Y, - const ArrayView& own_secret, - ArrayView shared_secret + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret ); private: - void load_mpi(mbedtls_mpi& dest, const ArrayView& src); + void load_mpi(mbedtls_mpi& dest, const ArrayView& src); - void store_mpi(ArrayView& dest, const mbedtls_mpi& src); - - void swap_endian(ArrayView& to_swap); + void store_mpi(ArrayView& dest, const mbedtls_mpi& src); void swap_endian(uint8_t* buf, size_t len); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index e6f00eccc5..e91de1b168 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -105,9 +105,9 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { if (_crypto.generate_keys( - make_ArrayView(X.buffer(), X.size()), - make_ArrayView(Y.buffer(), Y.size()), - make_ArrayView(secret.buffer(), secret.size()) + make_ArrayView(X), + make_ArrayView(Y), + make_ArrayView(secret) )) { return BLE_ERROR_NONE; } @@ -800,13 +800,13 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = gap_evt.params.lesc_dhkey_request; - size_t key_size = public_key_coord_t::size(); + static const size_t key_size = public_key_coord_t::size_; ble_gap_lesc_dhkey_t shared_secret; _crypto.generate_shared_secret( - make_const_ArrayView(dhkey_request.p_pk_peer->pk, key_size), - make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size, key_size), - make_const_ArrayView(secret.data(), secret.size()), + make_const_ArrayView(dhkey_request.p_pk_peer->pk), + make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size), + make_const_ArrayView(secret), shared_secret.key ); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index f9263998ad..31bda5bbcc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -337,7 +337,7 @@ private: void release_all_pairing_cb(); pairing_control_block_t* _control_blocks; - LescCrypto _crypto; + CryptoToolbox _crypto; ble::public_key_coord_t X; ble::public_key_coord_t Y; ble::public_key_coord_t secret; From 04ab07ff16de758002eafb363a0bbd3b8de119ec Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:41:20 +0100 Subject: [PATCH 073/274] BLE: Add documentation to CryptoToolbox. --- .../TARGET_NRF5/source/nRF5xCrypto.h | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index 1d1f432d4f..0189e44ddc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -17,50 +17,70 @@ #ifndef NRF5X_CRYPTO_ #define NRF5X_CRYPTO_ -#include +#include #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif -#include -#include - #include "mbedtls/platform.h" -#include "mbedtls/ecdh.h" -#include "mbedtls/memory_buffer_alloc.h" #include "mbedtls/entropy.h" #include "mbedtls/ecp.h" #include "platform/NonCopyable.h" -#include "platform/CriticalSectionLock.h" #include "ble/BLETypes.h" -#include "cmsis.h" -#include "ble/ArrayView.h" namespace ble { namespace pal { namespace vendor { namespace nordic { +/** + * Toolbox of cryptographic functions used in BLE. + */ class CryptoToolbox : mbed::NonCopyable { public: + /** + * Size of the Key used in lesc crypto operations. + */ static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; - + /** + * Create a new CryptoToolbox. + */ CryptoToolbox(); + /** + * Destroy a CryptoTioolbox object. + */ ~CryptoToolbox(); + /** + * Generate lesc public and private keys. + * @param[out] X The component X of the public key. + * @param[out] Y The component Y of the public key. + * @param[out] secret The secret key. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ bool generate_keys( ArrayView X, ArrayView Y, ArrayView secret ); + /** + * Generate a shared secret from a peer public key and a local secret key. + * @param[in] peer_X The component X of the peer public key. + * @param[in] peer_Y The component Y of the peer public key. + * @param[in] own_secret The local secret key. + * @param[out] shared_secret The shared secret generated. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ bool generate_shared_secret( const ArrayView& peer_X, const ArrayView& peer_Y, @@ -69,7 +89,6 @@ public: ); private: - void load_mpi(mbedtls_mpi& dest, const ArrayView& src); void store_mpi(ArrayView& dest, const mbedtls_mpi& src); From 17b3e2642977fafe2a8be661f2d4d49ff9ba28ce Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 15:42:47 +0100 Subject: [PATCH 074/274] BLE: remove trace in Nordic PAL security manager --- .../TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index e91de1b168..9aa8b61b58 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -179,7 +179,6 @@ ble_error_t nRF5xSecurityManager::send_pairing_request( KeyDistribution initiator_dist, KeyDistribution responder_dist ) { - printf("nRF5xSecurityManager::send_pairing_request\r\n"); // allocate the control block required for the procedure completion pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); if (!pairing_cb) { From 539a11ee3116230a013d393e40c4ee5d7827fdbe Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 4 Apr 2018 15:59:10 +0100 Subject: [PATCH 075/274] sign counter added --- .../ble/generic/GenericSecurityManager.h | 23 ++++++++++--- features/FEATURE_BLE/ble/pal/AttClient.h | 4 ++- .../ble/pal/AttClientToGattClientAdapter.h | 17 ++++++++-- .../FEATURE_BLE/ble/pal/MemorySecurityDB.h | 29 ++++++++++++++-- features/FEATURE_BLE/ble/pal/PalGattClient.h | 20 ++++++++++- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 16 +++++++-- features/FEATURE_BLE/ble/pal/SecurityDb.h | 33 +++++++++++++++++-- .../source/generic/GenericGattClient.cpp | 5 ++- .../source/generic/GenericSecurityManager.cpp | 23 ++++++++++--- .../TARGET_CORDIO/CordioPalAttClient.h | 5 +-- .../TARGET_CORDIO/CordioPalSecurityManager.h | 3 +- .../source/CordioPalSecurityManager.cpp | 3 +- .../TARGET_NRF5/source/nRF5XPalGattClient.cpp | 11 ++++++- .../TARGET_NRF5/source/nRF5XPalGattClient.h | 11 ++++++- 14 files changed, 178 insertions(+), 25 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 7fe92b3b30..c7ea499b69 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -251,6 +251,10 @@ public: _oob_local_random[0] = 1; } + uint32_t get_next_sign_counter() { + return _local_sign_counter++; + } + //////////////////////////////////////////////////////////////////////////// // Helper functions // @@ -326,7 +330,8 @@ private: */ void return_csrk_cb( pal::SecurityDb::entry_handle_t connection, - const csrk_t *csrk + const csrk_t *csrk, + uint32_t sign_counter ); /** @@ -337,7 +342,8 @@ private: */ void set_peer_csrk_cb( pal::SecurityDb::entry_handle_t connection, - const csrk_t *csrk + const csrk_t *csrk, + uint32_t sign_counter ); /** @@ -471,6 +477,8 @@ private: address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */ oob_tk_t _oob_temporary_key; /**< used for legacy pairing */ + uint32_t _local_sign_counter; + pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; @@ -526,9 +534,16 @@ public: connection_handle_t connection ); - /** @copydoc ble::pal::SecurityManager::on_signature_verification_failure + /** @copydoc ble::pal::SecurityManager::on_signed_write_received */ - virtual void on_signature_verification_failure( + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ); + + /** @copydoc ble::pal::SecurityManager::on_signed_write_verification_failure + */ + virtual void on_signed_write_verification_failure( connection_handle_t connection ); diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h index 56bd1a2f06..061b19b6a1 100644 --- a/features/FEATURE_BLE/ble/pal/AttClient.h +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -485,6 +485,7 @@ struct AttClient { * request to. * @param attribute_handle Handle of the attribute to write. * @param value Value to write. It can't be longer than (mtu - 15). + * @param sign_counter Signed write counter to use for this command. * * @note the authentication signature to send with this request is * computed by the implementation following the rules defined in BLUETOOTH @@ -498,7 +499,8 @@ struct AttClient { virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h index d99a55e497..d2cbcead56 100644 --- a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -221,15 +221,28 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter ) { return _client.signed_write_command( connection_handle, characteristic_value_handle, - value + value, + sign_counter ); } + /** + * @see ble::pal::GattClient::set_peer_signing_counter + */ + virtual ble_error_t set_peer_signing_counter( + connection_handle_t connection_handle, + uint32_t sign_counter + ) { + /* TODO: implement*/ + return BLE_ERROR_NOT_IMPLEMENTED; + } + /** * @see ble::pal::GattClient::write_attribute */ diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index a9ae337d03..80d68353cb 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -32,12 +32,13 @@ private: }; struct entry_t { - entry_t() : state(ENTRY_FREE) { }; + 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; + uint32_t sign_counter; state_t state; }; static const size_t MAX_ENTRIES = 5; @@ -151,11 +152,13 @@ public: entry_handle_t entry_handle ) { csrk_t csrk; + uint32_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); + cb(entry_handle, &csrk, sign_counter); } virtual void get_entry_peer_keys( @@ -230,6 +233,17 @@ public: } } + virtual void set_entry_peer_sign_counter( + entry_handle_t entry_handle, + uint32_t sign_counter + ) { + entry_t *entry = as_entry(entry_handle); + if (entry) { + entry->state = ENTRY_WRITTEN; + entry->sign_counter = sign_counter; + } + } + /* local csrk */ virtual const csrk_t* get_local_csrk() { @@ -240,6 +254,16 @@ public: _local_csrk = csrk; } + virtual uint32_t get_local_sign_counter() { + return _local_sign_counter; + } + + virtual void set_local_sign_counter( + uint32_t sign_counter + ) { + _local_sign_counter = sign_counter; + } + /* list management */ virtual entry_handle_t open_entry( @@ -344,6 +368,7 @@ private: entry_t _entries[MAX_ENTRIES]; SecurityEntryIdentity_t _local_identity; csrk_t _local_csrk; + uint32_t _local_sign_counter; }; } /* namespace pal */ diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h index 2152c428f4..70349ebce0 100644 --- a/features/FEATURE_BLE/ble/pal/PalGattClient.h +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -455,13 +455,31 @@ public: * @param connection_handle The handle of the connection to send this request to. * @param attribute_handle Handle of the attribute to write. * @param value The value to write. + * @param sign_counter Signed write counter to use for this command. * * @return BLE_ERROR_NONE or an appropriate error. */ virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter + ) = 0; + + /** + * Set the signing counter associated with the peer. This counter will be used + * to verify the signed messages coming from that peer. + * + * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H Section 2.4.5 + * + * @param connection_handle The handle of the connection for the peer. + * @param sign_counter Counter used to verify incoming signed messages. + * + * @return BLE_ERROR_NONE or an appropriate error. + */ + virtual ble_error_t set_peer_signing_counter( + connection_handle_t connection_handle, + uint32_t sign_counter ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 9b98f8e3b7..c0ffc4aa21 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -280,13 +280,24 @@ public: connection_handle_t connection ) = 0; + /** + * Set new signed write peer counter. + * + * @param[in] connection connection handle + * @param[in] sign_coutner counter received from peer + */ + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ) = 0; + /** * Indicate that signed data was rejected due to verification failure. This could * be due to an invalid CSRK key. * * @param[in] connection connection handle */ - virtual void on_signature_verification_failure( + virtual void on_signed_write_verification_failure( connection_handle_t connection ) = 0; @@ -885,7 +896,8 @@ public: virtual ble_error_t set_peer_csrk( connection_handle_t connection, const csrk_t &csrk, - bool authenticated + bool authenticated, + uint32_t sign_counter ) = 0; //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 52dd3a8646..5b7c656eef 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -101,7 +101,7 @@ public: typedef mbed::Callback SecurityEntryKeysDbCb_t; - typedef mbed::Callback + typedef mbed::Callback SecurityEntryCsrkDbCb_t; typedef mbed::Callback WhitelistDbCb_t; @@ -270,6 +270,17 @@ public: const csrk_t &csrk ) = 0; + /** + * Update peer signing counter. + * + * @param[in] db_entry 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, + uint32_t sign_counter + ) = 0; + /* local csrk */ /** @@ -279,12 +290,30 @@ public: */ virtual const csrk_t* get_local_csrk() = 0; + /** + * Return local signing counter. + * + * @return signing counter + */ + virtual uint32_t get_local_sign_counter() = 0; + /** * Update local signing key. * * @param[in] csrk new CSRK value */ - virtual void set_local_csrk(const csrk_t &csrk) = 0; + virtual void set_local_csrk( + const csrk_t &csrk + ) = 0; + + /** + * Update local signing counter. + * + * @param[in] sign_counter new signing counter value + */ + virtual void set_local_sign_counter( + uint32_t sign_counter + ) = 0; /* list management */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 4962b9dd2b..83c577f259 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1097,10 +1097,13 @@ ble_error_t GenericGattClient::write( if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } + GenericSecurityManager* sm = (GenericSecurityManager*)(&createBLEInstance()->getSecurityManager()); + const uint32_t sign_counter = sm->get_next_sign_counter(); return _pal_client->signed_write_without_response( connection_handle, attribute_handle, - make_const_ArrayView(value, length) + make_const_ArrayView(value, length), + sign_counter ); } else { uint8_t* data = NULL; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index a079c58c68..b7ef84330f 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -640,6 +640,7 @@ ble_error_t GenericSecurityManager::oobReceived( ble_error_t GenericSecurityManager::init_signing() { const csrk_t *pcsrk = _db.get_local_csrk(); + _local_sign_counter = _db.get_local_sign_counter(); if (!pcsrk) { csrk_t csrk; @@ -650,6 +651,7 @@ ble_error_t GenericSecurityManager::init_signing() { pcsrk = &csrk; _db.set_local_csrk(csrk); + _db.set_local_sign_counter(_local_sign_counter); } return _pal.set_csrk(*pcsrk); } @@ -735,7 +737,8 @@ void GenericSecurityManager::set_ltk_cb( void GenericSecurityManager::set_peer_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, - const csrk_t *csrk + const csrk_t *csrk, + uint32_t sign_counter ) { ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { @@ -745,13 +748,15 @@ void GenericSecurityManager::set_peer_csrk_cb( _pal.set_peer_csrk( cb->connection, *csrk, - cb->csrk_mitm_protected + cb->csrk_mitm_protected, + sign_counter ); } void GenericSecurityManager::return_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, - const csrk_t *csrk + const csrk_t *csrk, + uint32_t sign_counter ) { ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { @@ -942,8 +947,18 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t connection void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) { (void)connection; } +void GenericSecurityManager::on_signed_write_received( + connection_handle_t connection, + uint32_t sign_counter +) { + ControlBlock_t *cb = get_control_block(connection); + if (!cb) { + return; + } + _db.set_entry_peer_sign_counter(cb->db_entry, sign_counter); +} -void GenericSecurityManager::on_signature_verification_failure( +void GenericSecurityManager::on_signed_write_verification_failure( connection_handle_t connection ) { ControlBlock_t *cb = get_control_block(connection); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 401cffa8b8..016b866add 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -211,12 +211,13 @@ public: virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter ) { AttcSignedWriteCmd( connection_handle, attribute_handle, - /* sign counter from flash or AttsGetSignCounter() ? */ 0, + sign_counter, value.size(), const_cast(value.data()) ); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index fe5da7d159..02b8522c27 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -245,7 +245,8 @@ public: virtual ble_error_t set_peer_csrk( connection_handle_t connection, const csrk_t &csrk, - bool authenticated + bool authenticated, + uint32_t sign_counter ); //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 5a02ea0e8c..73e03190f0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -275,7 +275,8 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) ble_error_t CordioSecurityManager::set_peer_csrk( connection_handle_t connection, const csrk_t &csrk, - bool authenticated + bool authenticated, + uint32_t sign_counter ) { /* TODO implement */ return BLE_ERROR_NOT_IMPLEMENTED; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp index cba1ea60d4..e9196e9003 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp @@ -300,7 +300,8 @@ ble_error_t nRF5XGattClient::write_without_response( ble_error_t nRF5XGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter ) { ble_gattc_write_params_t write_params = { BLE_GATT_OP_SIGN_WRITE_CMD, @@ -315,6 +316,14 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } +ble_error_t nRF5XGattClient::set_peer_signing_counter( + connection_handle_t connection_handle, + uint32_t sign_counter +) { + /* TODO: implement*/ + return BLE_ERROR_NOT_IMPLEMENTED; +} + ble_error_t nRF5XGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h index ede03ce3f4..c997a8a9d8 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h @@ -153,7 +153,16 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value + const ArrayView& value, + uint32_t sign_counter + ); + + /** + * see pal::GattClient::set_peer_signing_counter . + */ + virtual ble_error_t set_peer_signing_counter( + connection_handle_t connection_handle, + uint32_t sign_counter ); /** From 2e1c5fc12302c80a59f8644bb051132844f6e5b4 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 4 Apr 2018 17:16:16 +0100 Subject: [PATCH 076/274] completely redundant --- features/FEATURE_BLE/ble/pal/PalGattClient.h | 16 ---------------- .../TARGET_NRF5/source/nRF5XPalGattClient.cpp | 8 -------- 2 files changed, 24 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h index 70349ebce0..4dfdb31b6a 100644 --- a/features/FEATURE_BLE/ble/pal/PalGattClient.h +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -466,22 +466,6 @@ public: uint32_t sign_counter ) = 0; - /** - * Set the signing counter associated with the peer. This counter will be used - * to verify the signed messages coming from that peer. - * - * @note see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H Section 2.4.5 - * - * @param connection_handle The handle of the connection for the peer. - * @param sign_counter Counter used to verify incoming signed messages. - * - * @return BLE_ERROR_NONE or an appropriate error. - */ - virtual ble_error_t set_peer_signing_counter( - connection_handle_t connection_handle, - uint32_t sign_counter - ) = 0; - /** * Send a write request to the server. * diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp index e9196e9003..80d350c30f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp @@ -316,14 +316,6 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::set_peer_signing_counter( - connection_handle_t connection_handle, - uint32_t sign_counter -) { - /* TODO: implement*/ - return BLE_ERROR_NOT_IMPLEMENTED; -} - ble_error_t nRF5XGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, From acfc5b218d6943a0e6b96538d20790cd5b506b56 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 4 Apr 2018 17:16:34 +0100 Subject: [PATCH 077/274] set cordio csrk and counter --- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 73e03190f0..9136053fca 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -18,6 +18,7 @@ #include "CordioPalSecurityManager.h" #include "dm_api.h" +#include "att_api.h" #include "smp_api.h" #include "wsf_os.h" @@ -278,8 +279,10 @@ ble_error_t CordioSecurityManager::set_peer_csrk( bool authenticated, uint32_t sign_counter ) { - /* TODO implement */ - return BLE_ERROR_NOT_IMPLEMENTED; + AttsSetCsrk(connection, const_cast(csrk.data())); + AttsSetSignCounter(connection, sign_counter); + + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// From dcff8104574842268573700710c1b7d48c125a08 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 4 Apr 2018 17:20:08 +0100 Subject: [PATCH 078/274] BLE: replace byte_array_t::buffer with byte_array_t::data --- features/FEATURE_BLE/ble/BLETypes.h | 8 -------- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 6 +++--- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 2 +- .../TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp | 2 +- .../TARGET_NRF5/source/nRF5xPalSecurityManager.cpp | 4 ++-- 5 files changed, 7 insertions(+), 15 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index bbd6785bc2..a4b0c1da05 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -337,14 +337,6 @@ struct byte_array_t { return _value; } - - /** - * Return the pointer to the buffer holding data. - */ - uint8_t* buffer() { - return _value; - } - /** * Size in byte of a data. */ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 2acca2755f..50a77c870b 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -520,7 +520,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( cb->oob_mitm_protection = OOBProvidesMITM; _oob_temporary_key_creator_address = cb->local_address; - get_random_data(_oob_temporary_key.buffer(), 16); + get_random_data(_oob_temporary_key.data(), 16); eventHandler->legacyPairingOobGenerated( &_oob_temporary_key_creator_address, @@ -608,7 +608,7 @@ ble_error_t GenericSecurityManager::init_signing() { if (!pcsrk) { csrk_t csrk; - ble_error_t ret = get_random_data(csrk.buffer(), csrk.size()); + ble_error_t ret = get_random_data(csrk.data(), csrk.size()); if (ret != BLE_ERROR_NONE) { return ret; } @@ -630,7 +630,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size if (ret != BLE_ERROR_NONE) { return ret; } - memcpy(buffer, random_data.buffer(), copy_size); + memcpy(buffer, random_data.data(), copy_size); size -= copy_size; buffer += copy_size; } diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 2935fdcc41..ea07b71c48 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -357,7 +357,7 @@ ble_error_t CordioSecurityManager::cancel_pairing( ble_error_t CordioSecurityManager::get_random_data(byte_array_t<8> &random_data) { - SecRand(random_data.buffer(), random_data.size()); + SecRand(random_data.data(), random_data.size()); return BLE_ERROR_NOT_IMPLEMENTED; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp index c5a4012de2..ca875d805f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -131,7 +131,7 @@ bool CryptoToolbox::generate_shared_secret( void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { ble::public_key_coord_t src_be = src.data(); - swap_endian(src_be.buffer(), src_be.size()); + swap_endian(src_be.data(), src_be.size()); mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index 9aa8b61b58..08acfc4bdb 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -521,7 +521,7 @@ ble_error_t nRF5xSecurityManager::set_csrk(const csrk_t& csrk) ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) { uint32_t err = sd_rand_application_vector_get( - random_data.buffer(), random_data.size() + random_data.data(), random_data.size() ); return convert_sd_error(err); } @@ -636,7 +636,7 @@ ble_error_t nRF5xSecurityManager::generate_secure_connections_oob( ble_gap_lesc_p256_pk_t own_secret; ble_gap_lesc_oob_data_t oob_data; - memcpy(own_secret.pk, secret.buffer(), secret.size()); + memcpy(own_secret.pk, secret.data(), secret.size()); uint32_t err = sd_ble_gap_lesc_oob_data_get( connection, From 1d74dfa1f955b3d8219a6e32a6ccd62ad7786af9 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 4 Apr 2018 18:02:16 +0100 Subject: [PATCH 079/274] redundant funcs removed --- .../ble/pal/AttClientToGattClientAdapter.h | 11 ----------- .../TARGET_NRF5/source/nRF5XPalGattClient.h | 8 -------- 2 files changed, 19 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h index d2cbcead56..e9b4d7d75d 100644 --- a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -232,17 +232,6 @@ public: ); } - /** - * @see ble::pal::GattClient::set_peer_signing_counter - */ - virtual ble_error_t set_peer_signing_counter( - connection_handle_t connection_handle, - uint32_t sign_counter - ) { - /* TODO: implement*/ - return BLE_ERROR_NOT_IMPLEMENTED; - } - /** * @see ble::pal::GattClient::write_attribute */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h index c997a8a9d8..20b20296de 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h @@ -157,14 +157,6 @@ public: uint32_t sign_counter ); - /** - * see pal::GattClient::set_peer_signing_counter . - */ - virtual ble_error_t set_peer_signing_counter( - connection_handle_t connection_handle, - uint32_t sign_counter - ); - /** * see pal::GattClient::write_attribute . */ From 57149b69e41f6513fdb2ba5cc09691e248149b6c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 4 Apr 2018 19:24:00 +0100 Subject: [PATCH 080/274] monitor for signing events and set local counter --- .../ble/generic/GenericGattClient.h | 10 ++- .../ble/generic/GenericSecurityManager.h | 13 +++- features/FEATURE_BLE/ble/pal/AttClient.h | 4 +- .../ble/pal/AttClientToGattClientAdapter.h | 6 +- features/FEATURE_BLE/ble/pal/PalGattClient.h | 4 +- .../FEATURE_BLE/ble/pal/PalSecurityManager.h | 29 ++------ .../FEATURE_BLE/ble/pal/SigningEventMonitor.h | 74 +++++++++++++++++++ .../source/generic/GenericGattClient.cpp | 18 +++-- .../source/generic/GenericSecurityManager.cpp | 14 +++- .../TARGET_CORDIO/CordioPalAttClient.h | 5 +- .../TARGET_CORDIO/CordioPalSecurityManager.h | 6 +- .../TARGET_CORDIO/source/CordioBLE.cpp | 6 +- .../source/CordioPalSecurityManager.cpp | 8 +- .../TARGET_NRF5/source/nRF5XPalGattClient.cpp | 3 +- .../TARGET_NRF5/source/nRF5XPalGattClient.h | 3 +- 15 files changed, 148 insertions(+), 55 deletions(-) create mode 100644 features/FEATURE_BLE/ble/pal/SigningEventMonitor.h diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h index f0a8462ff9..7dbb0e185d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGattClient.h +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -20,6 +20,7 @@ #include #include "ble/GattClient.h" #include "ble/pal/PalGattClient.h" +#include "ble/pal/SigningEventMonitor.h" // IMPORTANT: private header. Not part of the public interface. @@ -31,7 +32,8 @@ namespace generic { * It requires a pal::GattClient injected at construction site. * @attention: Not part of the public interface of BLE API. */ -class GenericGattClient : public GattClient { +class GenericGattClient : public GattClient, + public pal::SigningEventMonitor { public: /** * Create a GenericGattClient from a pal::GattClient @@ -114,6 +116,11 @@ public: */ virtual ble_error_t reset(void); + /** + * @see ble::pal::SigningEventMonitor::set_signing_event_handler + */ + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *signing_event_handler); + private: struct ProcedureControlBlock; struct DiscoveryControlBlock; @@ -136,6 +143,7 @@ private: pal::GattClient* const _pal_client; ServiceDiscovery::TerminationCallback_t _termination_callback; + pal::SigningEventMonitor::EventHandler* _signing_event_handler; mutable ProcedureControlBlock* control_blocks; bool _is_reseting; }; diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index c7ea499b69..315627afdc 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -22,6 +22,7 @@ #include "ble/pal/SecurityDb.h" #include "platform/Callback.h" #include "ble/pal/ConnectionEventMonitor.h" +#include "ble/pal/SigningEventMonitor.h" #include "ble/generic/GenericGap.h" #include "ble/pal/PalSecurityManager.h" @@ -32,7 +33,8 @@ typedef SecurityManager::SecurityIOCapabilities_t SecurityIOCapabilities_t; class GenericSecurityManager : public SecurityManager, public pal::SecurityManager::EventHandler, - public pal::ConnectionEventMonitor::EventHandler { + public pal::ConnectionEventMonitor::EventHandler, + public pal::SigningEventMonitor::EventHandler { public: typedef ble::pal::SecurityDistributionFlags_t SecurityDistributionFlags_t; typedef ble::pal::SecurityEntryKeys_t SecurityEntryKeys_t; @@ -234,10 +236,12 @@ public: GenericSecurityManager( pal::SecurityManager &palImpl, pal::SecurityDb &dbImpl, - pal::ConnectionEventMonitor &connMonitorImpl + pal::ConnectionEventMonitor &connMonitorImpl, + pal::SigningEventMonitor &signingMonitorImpl ) : _pal(palImpl), _db(dbImpl), _connection_monitor(connMonitorImpl), + _signing_monitor(signingMonitorImpl), _default_authentication(0), _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), @@ -467,6 +471,7 @@ private: pal::SecurityManager &_pal; pal::SecurityDb &_db; pal::ConnectionEventMonitor &_connection_monitor; + pal::SigningEventMonitor &_signing_monitor; /* OOB data */ address_t _oob_local_address; @@ -547,6 +552,10 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_signed_write + */ + virtual void on_signed_write(); + /** @copydoc ble::pal::SecurityManager::on_slave_security_request */ virtual void on_slave_security_request( diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h index 061b19b6a1..56bd1a2f06 100644 --- a/features/FEATURE_BLE/ble/pal/AttClient.h +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -485,7 +485,6 @@ struct AttClient { * request to. * @param attribute_handle Handle of the attribute to write. * @param value Value to write. It can't be longer than (mtu - 15). - * @param sign_counter Signed write counter to use for this command. * * @note the authentication signature to send with this request is * computed by the implementation following the rules defined in BLUETOOTH @@ -499,8 +498,7 @@ struct AttClient { virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h index e9b4d7d75d..d99a55e497 100644 --- a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -221,14 +221,12 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { return _client.signed_write_command( connection_handle, characteristic_value_handle, - value, - sign_counter + value ); } diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h index 4dfdb31b6a..2152c428f4 100644 --- a/features/FEATURE_BLE/ble/pal/PalGattClient.h +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -455,15 +455,13 @@ public: * @param connection_handle The handle of the connection to send this request to. * @param attribute_handle Handle of the attribute to write. * @param value The value to write. - * @param sign_counter Signed write counter to use for this command. * * @return BLE_ERROR_NONE or an appropriate error. */ virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index c0ffc4aa21..fe942a0aa8 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -280,27 +280,6 @@ public: connection_handle_t connection ) = 0; - /** - * Set new signed write peer counter. - * - * @param[in] connection connection handle - * @param[in] sign_coutner counter received from peer - */ - virtual void on_signed_write_received( - connection_handle_t connection, - uint32_t sign_coutner - ) = 0; - - /** - * Indicate that signed data was rejected due to verification failure. This could - * be due to an invalid CSRK key. - * - * @param[in] connection connection handle - */ - virtual void on_signed_write_verification_failure( - connection_handle_t connection - ) = 0; - /** * Ask the stack to evaluate the security request received from the slave. * This might result in the stack enabling encryption, or pairing/re-pairing. @@ -879,11 +858,13 @@ public: /** * Set the local CSRK. * - * @param[in] csrk signing key + * @param[in] csrk local signing key + * @param[in] sign_counter local signing counter * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_csrk( - const csrk_t &csrk + const csrk_t &csrk, + uint32_t sign_counter ) = 0; /** @@ -891,6 +872,8 @@ public: * * @param[in] connection connection handle * @param[in] csrk signing key + * @param[in] authenticated is the CSRK authenticated + * @param[in] sign_counter signing counter * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_peer_csrk( diff --git a/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h new file mode 100644 index 0000000000..bc6392c8be --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h @@ -0,0 +1,74 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 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 MBED_BLE_SIGNING_EVENT_MONITOR +#define MBED_BLE_SIGNING_EVENT_MONITOR + +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { + +/** + * Implemented by classes that need to be notified of signing events. + * Notification is done by calling functions in the passed in event handler + */ +class SigningEventMonitor { +public: + /** + * Implemented by classes that are reacting to signing events. + */ + class EventHandler { + public: + /** + * Set new signed write peer counter. + * + * @param[in] connection connection handle + * @param[in] sign_coutner counter received from peer + */ + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ) = 0; + + /** + * Indicate that signed data was rejected due to verification failure. This could + * be due to an invalid CSRK key. + * + * @param[in] connection connection handle + */ + virtual void on_signed_write_verification_failure( + connection_handle_t connection + ) = 0; + + /** + * Notify a new signed write cmd was executed. + */ + virtual void on_signed_write() = 0; + }; + + /** + * Register a handler for singing events to be used internally and serviced first. + * + * @param[in] signing_event_handler Event handler being registered. + */ + virtual void set_signing_event_handler(EventHandler *signing_event_handler) = 0; +}; + +} // namespace pal +} // namespace ble + +#endif /* MBED_BLE_SIGNING_EVENT_MONITOR */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 83c577f259..088e120dd6 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -936,6 +936,7 @@ struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureCont GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : _pal_client(pal_client), _termination_callback(), + _signing_event_handler(NULL), control_blocks(NULL), _is_reseting(false) { _pal_client->when_server_message_received( @@ -1097,14 +1098,15 @@ ble_error_t GenericGattClient::write( if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } - GenericSecurityManager* sm = (GenericSecurityManager*)(&createBLEInstance()->getSecurityManager()); - const uint32_t sign_counter = sm->get_next_sign_counter(); - return _pal_client->signed_write_without_response( + ble_error_t status = _pal_client->signed_write_without_response( connection_handle, attribute_handle, - make_const_ArrayView(value, length), - sign_counter + make_const_ArrayView(value, length) ); + if (_signing_event_handler && (status == BLE_ERROR_NONE)) { + _signing_event_handler->on_signed_write(); + } + return status; } else { uint8_t* data = NULL; @@ -1257,6 +1259,12 @@ ble_error_t GenericGattClient::reset(void) { return BLE_ERROR_NONE; } +void GenericGattClient::set_signing_event_handler( + EventHandler *signing_event_handler +) { + _signing_event_handler = signing_event_handler; +} + void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { if (_termination_callback) { _termination_callback(connection_handle); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index b7ef84330f..dd37331504 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -71,6 +71,7 @@ ble_error_t GenericSecurityManager::init( } _connection_monitor.set_connection_event_handler(this); + _signing_monitor.set_signing_event_handler(this); _pal.set_event_handler(this); return BLE_ERROR_NONE; @@ -640,7 +641,8 @@ ble_error_t GenericSecurityManager::oobReceived( ble_error_t GenericSecurityManager::init_signing() { const csrk_t *pcsrk = _db.get_local_csrk(); - _local_sign_counter = _db.get_local_sign_counter(); + uint32_t local_sign_counter = _db.get_local_sign_counter(); + if (!pcsrk) { csrk_t csrk; @@ -651,9 +653,10 @@ ble_error_t GenericSecurityManager::init_signing() { pcsrk = &csrk; _db.set_local_csrk(csrk); - _db.set_local_sign_counter(_local_sign_counter); + _db.set_local_sign_counter(local_sign_counter); } - return _pal.set_csrk(*pcsrk); + + return _pal.set_csrk(*pcsrk, local_sign_counter); } ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) { @@ -947,6 +950,7 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t connection void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) { (void)connection; } + void GenericSecurityManager::on_signed_write_received( connection_handle_t connection, uint32_t sign_counter @@ -983,6 +987,10 @@ void GenericSecurityManager::on_signed_write_verification_failure( } } +void GenericSecurityManager::on_signed_write() { + _db.set_local_sign_counter(_db.get_local_sign_counter() + 1); +} + void GenericSecurityManager::on_slave_security_request( connection_handle_t connection, AuthenticationMask authentication diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 016b866add..eb64bafaee 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -211,13 +211,12 @@ public: virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { AttcSignedWriteCmd( connection_handle, attribute_handle, - sign_counter, + /*TODO: get sign counter from cordio sm */0, value.size(), const_cast(value.data()) ); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 02b8522c27..c9bc5bc779 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -237,7 +237,10 @@ public: /** * @see ::ble::pal::SecurityManager::set_csrk */ - virtual ble_error_t set_csrk(const csrk_t &csrk); + virtual ble_error_t set_csrk( + const csrk_t &csrk, + uint32_t sign_counter + ); /** * @see ::ble::pal::SecurityManager::set_peer_csrk @@ -321,6 +324,7 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; + uint32_t _local_sign_counter; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 93a5327012..e6d01ef6b3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -219,10 +219,14 @@ const SecurityManager& BLE::getSecurityManager() const { static pal::MemorySecurityDb m_db; pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); + + BLE *self = const_cast(this); + static generic::GenericSecurityManager m_instance( m_pal, m_db, - const_cast(getGenericGap()) + const_cast(getGenericGap()), + static_cast(self->getGattClient()) ); return m_instance; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 9136053fca..6bf678c5d5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -31,6 +31,7 @@ CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), _default_passkey(0), + _local_sign_counter(0), _lesc_keys_generated(false), _public_key_x() { @@ -267,8 +268,11 @@ ble_error_t CordioSecurityManager::set_irk(const irk_t& irk) return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) -{ +ble_error_t CordioSecurityManager::set_csrk( + const csrk_t& csrk, + uint32_t sign_counter +) { + _local_sign_counter = sign_counter; DmSecSetLocalCsrk(const_cast(csrk.data())); return BLE_ERROR_NONE; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp index 80d350c30f..cba1ea60d4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp @@ -300,8 +300,7 @@ ble_error_t nRF5XGattClient::write_without_response( ble_error_t nRF5XGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { ble_gattc_write_params_t write_params = { BLE_GATT_OP_SIGN_WRITE_CMD, diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h index 20b20296de..ede03ce3f4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h @@ -153,8 +153,7 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ); /** From be912ded5bc853f917f2135d0fd563988b9c5d5a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 9 Apr 2018 12:14:52 +0100 Subject: [PATCH 081/274] normalised the getters const insanity --- .../targets/TARGET_CORDIO/CordioBLE.h | 6 ++--- .../TARGET_CORDIO/source/CordioBLE.cpp | 24 +++++++------------ 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index cdfc1aee48..e63d62055a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -85,12 +85,12 @@ public: /** * @see BLEInstanceBase::getGap */ - virtual ::Gap& getGap(); + virtual generic::GenericGap& getGap(); /** * @see BLEInstanceBase::getGap */ - virtual const ::Gap& getGap() const; + virtual const generic::GenericGap& getGap() const; /** * @see BLEInstanceBase::getGattServer @@ -105,7 +105,7 @@ public: /** * @see BLEInstanceBase::getGattClient */ - virtual ::GattClient &getGattClient(); + virtual generic::GenericGattClient &getGattClient(); /** * @see BLEInstanceBase::getSecurityManager diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index e6d01ef6b3..7ab3c61a53 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -164,19 +164,12 @@ const char* BLE::getVersion() return version; } -::Gap& BLE::getGap() +generic::GenericGap& BLE::getGap() { - typedef ::Gap& return_type; - const BLE* self = this; - return const_cast(self->getGap()); + return const_cast(getGap()); } -const ::Gap& BLE::getGap() const -{ - return getGenericGap(); -}; - -const generic::GenericGap& BLE::getGenericGap() const +const generic::GenericGap& BLE::getGap() const { static pal::vendor::cordio::Gap& cordio_pal_gap = pal::vendor::cordio::Gap::get_gap(); @@ -187,7 +180,7 @@ const generic::GenericGap& BLE::getGenericGap() const cordio_gap_service ); return gap; -} +}; GattServer& BLE::getGattServer() { @@ -199,7 +192,7 @@ const GattServer& BLE::getGattServer() const return cordio::GattServer::getInstance(); } -::GattClient& BLE::getGattClient() +generic::GenericGattClient& BLE::getGattClient() { static pal::AttClientToGattClientAdapter pal_client( pal::vendor::cordio::CordioAttClient::get_client() @@ -211,8 +204,7 @@ const GattServer& BLE::getGattServer() const SecurityManager& BLE::getSecurityManager() { - const BLE* self = this; - return const_cast(self->getSecurityManager()); + return const_cast(getSecurityManager()); } const SecurityManager& BLE::getSecurityManager() const @@ -225,8 +217,8 @@ const SecurityManager& BLE::getSecurityManager() const static generic::GenericSecurityManager m_instance( m_pal, m_db, - const_cast(getGenericGap()), - static_cast(self->getGattClient()) + self->getGap(), + self->getGattClient() ); return m_instance; From 55d3423a5ee7717389b9b15b758ac397c294e489 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 9 Apr 2018 13:35:17 +0100 Subject: [PATCH 082/274] typedef uint32_t --- features/FEATURE_BLE/ble/BLETypes.h | 3 +++ .../FEATURE_BLE/ble/generic/GenericSecurityManager.h | 8 ++++---- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 12 ++++++------ features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 4 ++-- features/FEATURE_BLE/ble/pal/SecurityDb.h | 6 +++--- .../source/generic/GenericSecurityManager.cpp | 8 ++++---- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 6 +++--- .../source/CordioPalSecurityManager.cpp | 4 ++-- 8 files changed, 27 insertions(+), 24 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 8095345657..871e6bea35 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -379,6 +379,9 @@ typedef byte_array_t<32> public_key_coord_t; /** Diffie-Hellman key */ typedef byte_array_t<32> dhkey_t; +/* counter for signed data writes done by GattClient */ +typedef uint32_t sign_count_t; + /** * MAC address data type. */ diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 315627afdc..4f26909645 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -255,7 +255,7 @@ public: _oob_local_random[0] = 1; } - uint32_t get_next_sign_counter() { + sign_count_t get_next_sign_counter() { return _local_sign_counter++; } @@ -335,7 +335,7 @@ private: void return_csrk_cb( pal::SecurityDb::entry_handle_t connection, const csrk_t *csrk, - uint32_t sign_counter + sign_count_t sign_counter ); /** @@ -347,7 +347,7 @@ private: void set_peer_csrk_cb( pal::SecurityDb::entry_handle_t connection, const csrk_t *csrk, - uint32_t sign_counter + sign_count_t sign_counter ); /** @@ -482,7 +482,7 @@ private: address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */ oob_tk_t _oob_temporary_key; /**< used for legacy pairing */ - uint32_t _local_sign_counter; + sign_count_t _local_sign_counter; pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index 80d68353cb..eb28867734 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -38,7 +38,7 @@ private: SecurityEntryKeys_t local_keys; SecurityEntryIdentity_t peer_identity; csrk_t csrk; - uint32_t sign_counter; + sign_count_t sign_counter; state_t state; }; static const size_t MAX_ENTRIES = 5; @@ -152,7 +152,7 @@ public: entry_handle_t entry_handle ) { csrk_t csrk; - uint32_t sign_counter = 0; + sign_count_t sign_counter = 0; entry_t *entry = as_entry(entry_handle); if (entry) { csrk = entry->csrk; @@ -235,7 +235,7 @@ public: virtual void set_entry_peer_sign_counter( entry_handle_t entry_handle, - uint32_t sign_counter + sign_count_t sign_counter ) { entry_t *entry = as_entry(entry_handle); if (entry) { @@ -254,12 +254,12 @@ public: _local_csrk = csrk; } - virtual uint32_t get_local_sign_counter() { + virtual sign_count_t get_local_sign_counter() { return _local_sign_counter; } virtual void set_local_sign_counter( - uint32_t sign_counter + sign_count_t sign_counter ) { _local_sign_counter = sign_counter; } @@ -368,7 +368,7 @@ private: entry_t _entries[MAX_ENTRIES]; SecurityEntryIdentity_t _local_identity; csrk_t _local_csrk; - uint32_t _local_sign_counter; + sign_count_t _local_sign_counter; }; } /* namespace pal */ diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index fe942a0aa8..4f100a0588 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -864,7 +864,7 @@ public: */ virtual ble_error_t set_csrk( const csrk_t &csrk, - uint32_t sign_counter + sign_count_t sign_counter ) = 0; /** @@ -880,7 +880,7 @@ public: connection_handle_t connection, const csrk_t &csrk, bool authenticated, - uint32_t sign_counter + sign_count_t sign_counter ) = 0; //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 5b7c656eef..62f67fb95b 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -278,7 +278,7 @@ public: */ virtual void set_entry_peer_sign_counter( entry_handle_t db_entry, - uint32_t sign_counter + sign_count_t sign_counter ) = 0; /* local csrk */ @@ -295,7 +295,7 @@ public: * * @return signing counter */ - virtual uint32_t get_local_sign_counter() = 0; + virtual sign_count_t get_local_sign_counter() = 0; /** * Update local signing key. @@ -312,7 +312,7 @@ public: * @param[in] sign_counter new signing counter value */ virtual void set_local_sign_counter( - uint32_t sign_counter + sign_count_t sign_counter ) = 0; /* list management */ diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index dd37331504..118ce77868 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -641,7 +641,7 @@ ble_error_t GenericSecurityManager::oobReceived( ble_error_t GenericSecurityManager::init_signing() { const csrk_t *pcsrk = _db.get_local_csrk(); - uint32_t local_sign_counter = _db.get_local_sign_counter(); + sign_count_t local_sign_counter = _db.get_local_sign_counter(); if (!pcsrk) { csrk_t csrk; @@ -741,7 +741,7 @@ void GenericSecurityManager::set_ltk_cb( void GenericSecurityManager::set_peer_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, const csrk_t *csrk, - uint32_t sign_counter + sign_count_t sign_counter ) { ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { @@ -759,7 +759,7 @@ void GenericSecurityManager::set_peer_csrk_cb( void GenericSecurityManager::return_csrk_cb( pal::SecurityDb::entry_handle_t db_entry, const csrk_t *csrk, - uint32_t sign_counter + sign_count_t sign_counter ) { ControlBlock_t *cb = get_control_block(db_entry); if (!cb) { @@ -953,7 +953,7 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection void GenericSecurityManager::on_signed_write_received( connection_handle_t connection, - uint32_t sign_counter + sign_count_t sign_counter ) { ControlBlock_t *cb = get_control_block(connection); if (!cb) { diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index c9bc5bc779..9a6cb9ffe1 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -239,7 +239,7 @@ public: */ virtual ble_error_t set_csrk( const csrk_t &csrk, - uint32_t sign_counter + sign_count_t sign_counter ); /** @@ -249,7 +249,7 @@ public: connection_handle_t connection, const csrk_t &csrk, bool authenticated, - uint32_t sign_counter + sign_count_t sign_counter ); //////////////////////////////////////////////////////////////////////////// @@ -324,7 +324,7 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; - uint32_t _local_sign_counter; + sign_count_t _local_sign_counter; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 6bf678c5d5..eb2ac8da37 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -270,7 +270,7 @@ ble_error_t CordioSecurityManager::set_irk(const irk_t& irk) ble_error_t CordioSecurityManager::set_csrk( const csrk_t& csrk, - uint32_t sign_counter + sign_count_t sign_counter ) { _local_sign_counter = sign_counter; DmSecSetLocalCsrk(const_cast(csrk.data())); @@ -281,7 +281,7 @@ ble_error_t CordioSecurityManager::set_peer_csrk( connection_handle_t connection, const csrk_t &csrk, bool authenticated, - uint32_t sign_counter + sign_count_t sign_counter ) { AttsSetCsrk(connection, const_cast(csrk.data())); AttsSetSignCounter(connection, sign_counter); From 637dcb9bc8445e3085b8718f4149e434356d1ebb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 9 Apr 2018 15:10:25 +0100 Subject: [PATCH 083/274] missing * --- features/FEATURE_BLE/ble/BLETypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 871e6bea35..84b69540db 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -379,7 +379,7 @@ typedef byte_array_t<32> public_key_coord_t; /** Diffie-Hellman key */ typedef byte_array_t<32> dhkey_t; -/* counter for signed data writes done by GattClient */ +/** counter for signed data writes done by GattClient */ typedef uint32_t sign_count_t; /** From deeb0ea7e0827316b9ee3e63c3d78ea410eadad0 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 9 Apr 2018 15:11:26 +0100 Subject: [PATCH 084/274] redundant store for sign counter --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 4f26909645..4ca681adae 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -255,10 +255,6 @@ public: _oob_local_random[0] = 1; } - sign_count_t get_next_sign_counter() { - return _local_sign_counter++; - } - //////////////////////////////////////////////////////////////////////////// // Helper functions // @@ -482,8 +478,6 @@ private: address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */ oob_tk_t _oob_temporary_key; /**< used for legacy pairing */ - sign_count_t _local_sign_counter; - pal::AuthenticationMask _default_authentication; pal::KeyDistribution _default_key_distribution; From 4fff20583df80a8c35a3265000c4e8079dc975aa Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 9 Apr 2018 17:49:54 +0100 Subject: [PATCH 085/274] sign counter kept track by the class using it --- .../targets/TARGET_CORDIO/CordioPalAttClient.h | 17 ++++++++++++++++- .../TARGET_CORDIO/CordioPalSecurityManager.h | 1 - .../source/CordioPalSecurityManager.cpp | 4 ++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index eb64bafaee..3d536aff52 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -216,13 +216,26 @@ public: AttcSignedWriteCmd( connection_handle, attribute_handle, - /*TODO: get sign counter from cordio sm */0, + _local_sign_counter, value.size(), const_cast(value.data()) ); + _local_sign_counter++; return BLE_ERROR_NONE; } + /** + * Initialises the counter used to sign messages. Counter will be incremented every + * time a message is signed. + * + * @param sign_counter initialise the signing counter to this value + */ + virtual void set_sign_counter( + sign_count_t sign_counter + ) { + _local_sign_counter = sign_counter; + } + /** * @see ble::pal::AttClient::prepare_write_request */ @@ -612,6 +625,8 @@ private: ); } }; +private: + sign_count_t _local_sign_counter; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 9a6cb9ffe1..d7a0a21cd9 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -324,7 +324,6 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; - sign_count_t _local_sign_counter; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index eb2ac8da37..3143dc1a1b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -17,6 +17,7 @@ #include #include "CordioPalSecurityManager.h" +#include "CordioBLE.h" #include "dm_api.h" #include "att_api.h" #include "smp_api.h" @@ -31,7 +32,6 @@ CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), _default_passkey(0), - _local_sign_counter(0), _lesc_keys_generated(false), _public_key_x() { @@ -272,7 +272,7 @@ ble_error_t CordioSecurityManager::set_csrk( const csrk_t& csrk, sign_count_t sign_counter ) { - _local_sign_counter = sign_counter; + CordioAttClient::get_client().set_sign_counter(sign_counter); DmSecSetLocalCsrk(const_cast(csrk.data())); return BLE_ERROR_NONE; } From a2484b63b0db55fa0ea612a717a772ca1b33d665 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 10 Apr 2018 14:58:29 +0100 Subject: [PATCH 086/274] Signing event monitor proxy to bind both server and client --- .../targets/TARGET_CORDIO/CordioGattServer.h | 15 ++++++++++++++- .../TARGET_CORDIO/source/CordioBLE.cpp | 19 ++++++++++++++++--- .../TARGET_CORDIO/source/CordioGattServer.cpp | 6 ++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index 26dc08a78e..15a758f723 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -20,6 +20,7 @@ #include #include "ble/blecommon.h" #include "ble/GattServer.h" +#include "ble/pal/SigningEventMonitor.h" #include "ble/Gap.h" #include "wsf_types.h" #include "att_api.h" @@ -34,7 +35,8 @@ namespace cordio { /** * Cordio implementation of ::GattServer */ -class GattServer : public ::GattServer +class GattServer : public ::GattServer, + public pal::SigningEventMonitor { public: /** @@ -147,6 +149,15 @@ public: */ virtual ble_error_t reset(void); + /** + * @see pal::SigningEventMonitor::set_signing_event_handler + */ + virtual void set_signing_event_handler( + pal::SigningEventMonitor::EventHandler *signing_event_handler + ) { + _signing_event_handler = signing_event_handler; + } + private: static void cccCback(attsCccEvt_t *pEvt); static void attCback(attEvt_t *pEvt); @@ -172,6 +183,8 @@ private: internal_service_t *next; }; + pal::SigningEventMonitor::EventHandler *_signing_event_handler; + attsCccSet_t cccSet[MAX_CCC_CNT]; uint16_t cccValues[MAX_CCC_CNT]; uint16_t cccHandles[MAX_CCC_CNT]; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 7ab3c61a53..bf0edb6ffe 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -209,16 +209,29 @@ SecurityManager& BLE::getSecurityManager() const SecurityManager& BLE::getSecurityManager() const { + class SigningEventMonitorProxy : public pal::SigningEventMonitor { + public: + SigningEventMonitorProxy(BLE &ble) : _ble(ble) { } + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *handler) { + _ble.getGattClient().set_signing_event_handler(handler); + _ble.getGattServer().set_signing_event_handler(handler); + } + private: + BLE &_ble; + }; + static pal::MemorySecurityDb m_db; pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); - BLE *self = const_cast(this); + BLE &self = const_cast(*this); + + static SigningEventMonitorProxy signing_event_monitor(self); static generic::GenericSecurityManager m_instance( m_pal, m_db, - self->getGap(), - self->getGattClient() + self.getGap(), + signing_event_monitor ); return m_instance; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 79173e39c9..93f543df7b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -585,6 +585,12 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o writeOp = GattWriteCallbackParams::OP_WRITE_CMD; break; case ATT_PDU_SIGNED_WRITE_CMD: + if (getInstance()._signing_event_handler) { + getInstance()._signing_event_handler->on_signed_write_received( + connId, + AttsGetSignCounter(connId) + ); + } writeOp = GattWriteCallbackParams::OP_SIGN_WRITE_CMD; break; case ATT_PDU_PREP_WRITE_REQ: From 70067105d6941ff280f24856ea065a8e37ebed7f Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 10 Apr 2018 16:42:43 +0100 Subject: [PATCH 087/274] class in header --- .../FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h | 11 +++++++++++ .../targets/TARGET_CORDIO/source/CordioBLE.cpp | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index e63d62055a..b5c7bb9ca5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -154,6 +154,17 @@ private: ::BLE::InstanceID_t instanceID; mutable pal::SimpleEventQueue _event_queue; + + class SigningEventMonitorProxy : public pal::SigningEventMonitor { + public: + SigningEventMonitorProxy(BLE &ble) : _ble(ble) { } + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *handler) { + _ble.getGattClient().set_signing_event_handler(handler); + _ble.getGattServer().set_signing_event_handler(handler); + } + private: + BLE &_ble; + }; }; } // namespace cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index bf0edb6ffe..d624dcbff4 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -209,17 +209,6 @@ SecurityManager& BLE::getSecurityManager() const SecurityManager& BLE::getSecurityManager() const { - class SigningEventMonitorProxy : public pal::SigningEventMonitor { - public: - SigningEventMonitorProxy(BLE &ble) : _ble(ble) { } - virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *handler) { - _ble.getGattClient().set_signing_event_handler(handler); - _ble.getGattServer().set_signing_event_handler(handler); - } - private: - BLE &_ble; - }; - static pal::MemorySecurityDb m_db; pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); From 1ba920a3385573833083ec7f130fcfc2358ac47c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 10 Apr 2018 16:47:29 +0100 Subject: [PATCH 088/274] missing init --- .../targets/TARGET_CORDIO/source/CordioGattServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 93f543df7b..91bba27650 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -819,7 +819,7 @@ void* GattServer::alloc_block(size_t block_size) { } GattServer::GattServer() : - ::GattServer(), cccSet(), cccValues(), cccHandles(), cccCnt(0), + ::GattServer(), _signing_event_handler(NULL), cccSet(), cccValues(), cccHandles(), cccCnt(0), generic_access_service(), generic_attribute_service(), registered_service(NULL), allocated_blocks(NULL), currentHandle(0) From 3aaedf6f48c772296b8e56fb0828be49b8ac2881 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 11 Apr 2018 12:34:57 +0100 Subject: [PATCH 089/274] fixed missed function rename --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 6b01c00a91..f73e5caccf 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -515,7 +515,7 @@ ble_error_t GenericSecurityManager::generateOOB( const address_t *address ) { /* legacy pairing */ - ble_error_t status = get_random_data(_oob_temporary_key.buffer(), 16); + ble_error_t status = get_random_data(_oob_temporary_key.data(), 16); if (status == BLE_ERROR_NONE) { _oob_temporary_key_creator_address = *address; From 1e6455da0ba868448e21e2ec082a1bb8293adc7c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 11 Apr 2018 13:37:04 +0100 Subject: [PATCH 090/274] check encryption before signing --- .../source/generic/GenericGattClient.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 088e120dd6..cbf61a9246 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1084,6 +1084,18 @@ ble_error_t GenericGattClient::write( uint16_t mtu = get_mtu(connection_handle); + /* if link is encrypted signed writes should be normal writes */ + if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { + ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + ble_error_t status = sm.getLinkEncryption(connection_handle, &encryption); + if (status == BLE_ERROR_NONE + || encryption == ble::link_encryption_t::ENCRYPTED + || encryption == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { + cmd = GattClient::GATT_OP_WRITE_CMD; + } + } + if (cmd == GattClient::GATT_OP_WRITE_CMD) { if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; @@ -1094,7 +1106,6 @@ ble_error_t GenericGattClient::write( make_const_ArrayView(value, length) ); } else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) { - /*TODO check encryption status */ if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } From 1f02913a2c6d7b880de5c82599a03e865ce6a015 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 11 Apr 2018 14:18:42 +0100 Subject: [PATCH 091/274] BLE: Add Gap privacy interfaces. This commit adds API to enable and configure the device privacy. It deprecates address random types present in Gap::AddressType as these types are not appropriate for scan reports, connection initiation and the connection event. Now user should use the function Gap::getRandomAddressType to find the type of a random address. The function gap::setAddress is deprecated as it is not portable and can colide with privacy. --- features/FEATURE_BLE/ble/BLEProtocol.h | 33 +++ features/FEATURE_BLE/ble/BLETypes.h | 18 ++ features/FEATURE_BLE/ble/Gap.h | 294 ++++++++++++++++++++++++- features/FEATURE_BLE/source/Gap.cpp | 36 +++ 4 files changed, 375 insertions(+), 6 deletions(-) create mode 100644 features/FEATURE_BLE/source/Gap.cpp diff --git a/features/FEATURE_BLE/ble/BLEProtocol.h b/features/FEATURE_BLE/ble/BLEProtocol.h index 4fdcb59bc5..79e3357bec 100644 --- a/features/FEATURE_BLE/ble/BLEProtocol.h +++ b/features/FEATURE_BLE/ble/BLEProtocol.h @@ -59,18 +59,51 @@ namespace BLEProtocol { */ PUBLIC = 0, + /** + * Random address. + * + * Use Gap::getRandomAddressType to retrieve the type of the random + * address. + */ + RANDOM, + + /** + * A Public address used as a device identity address. + */ + PUBLIC_IDENTITY, + + /** + * A Random static address used as a device identity address. + */ + RANDOM_STATIC_IDENTITY, + /** * Random static device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_STATIC, /** * Private resolvable device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_PRIVATE_RESOLVABLE, /** * Private non-resolvable device address. + * + * @deprecated This enumeration value is not relevant anymore. + * Advertising reporting and the connection procedure should rely + * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the + * type of the random address. */ RANDOM_PRIVATE_NON_RESOLVABLE }; diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index a5ece31757..41e4c99f13 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -442,6 +442,24 @@ struct address_t : public byte_array_t<6> { } }; +/** + * Type that describes a random device address type. + */ +struct random_address_type_t : SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + STATIC, /**< Random static device address. */ + NON_RESOLVABLE_PRIVATE, /**< Random non resolvable private address. */ + RESOLVABLE_PRIVATE /**< Random resolvable private address. */ + }; + + /** + * Construct a new instance of random_address_type_t. + */ + random_address_type_t(type value) : + SafeEnum(value) { } +}; + } // namespace ble /** diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index d42c5826fc..095c1c8bc2 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -294,6 +294,9 @@ public: */ enum DeprecatedAddressType_t { ADDR_TYPE_PUBLIC = BLEProtocol::AddressType::PUBLIC, + ADDR_TYPE_RANDOM = BLEProtocol::AddressType::RANDOM, + ADDR_TYPE_PUBLIC_IDENTITY = BLEProtocol::AddressType::PUBLIC_IDENTITY, + ADDR_TYPE_RANDOM_STATIC_IDENTITY = BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY, ADDR_TYPE_RANDOM_STATIC = BLEProtocol::AddressType::RANDOM_STATIC, ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE @@ -353,6 +356,12 @@ public: * disconnection reason to be transmitted to the peer. */ enum DisconnectionReason_t { + + /** + * GAP or GATT failed to authenticate the peer. + */ + AUTHENTICATION_FAILLURE = 0x05, + /** * The connection timed out. * @@ -496,6 +505,11 @@ public: */ typedef ble::connection_handle_t Handle_t; + /** + * Enumeration of random address types. + */ + typedef ble::random_address_type_t RandomAddressType_t; + /** * Parameters of a BLE connection. */ @@ -610,7 +624,10 @@ public: const uint8_t *advertisingData; /** - * Type of the address received + * Type of the address received. + * + * @note This value should be used in the connect function to establish + * a connection with the peer that has sent this advertisement packet. */ AddressType_t addressType; }; @@ -667,6 +684,20 @@ public: */ const ConnectionParams_t *connectionParams; + /** + * Resolvable address used by the peer. + * + * @note All bytes of the address are set to 0 if not applicable + */ + BLEProtocol::AddressBytes_t peerResolvableAddr; + + /** + * resolvable address of the local device. + * + * @note All bytes of the address are set to 0 if not applicable + */ + BLEProtocol::AddressBytes_t localResolvableAddr; + /** * Construct an instance of ConnectionCallbackParams_t. * @@ -677,6 +708,8 @@ public: * @param[in] ownAddrTypeIn Value to assign to ownAddrType. * @param[in] ownAddrIn Value to assign to ownAddr. * @param[in] connectionParamsIn Value to assign to connectionParams. + * @param[in] peerResolvableAddrIn Value to assign to peerResolvableAddr. + * @param[in] localResolvableAddrIn Value to assign to localResolvableAddr. * * @note Constructor is not meant to be called by user code. * The BLE API vendor code generates ConnectionCallbackParams_t. @@ -688,17 +721,28 @@ public: const uint8_t *peerAddrIn, BLEProtocol::AddressType_t ownAddrTypeIn, const uint8_t *ownAddrIn, - const ConnectionParams_t *connectionParamsIn + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn = NULL, + const uint8_t *localResolvableAddrIn = NULL ) : handle(handleIn), role(roleIn), peerAddrType(peerAddrTypeIn), peerAddr(), ownAddrType(ownAddrTypeIn), ownAddr(), - connectionParams(connectionParamsIn) + connectionParams(connectionParamsIn), + peerResolvableAddr(), + localResolvableAddr() { memcpy(peerAddr, peerAddrIn, ADDR_LEN); memcpy(ownAddr, ownAddrIn, ADDR_LEN); + if (peerResolvableAddrIn) { + memcpy(peerResolvableAddr, peerResolvableAddrIn, ADDR_LEN); + } + + if (localResolvableAddrIn) { + memcpy(localResolvableAddr, localResolvableAddrIn, ADDR_LEN); + } } }; @@ -736,6 +780,107 @@ public: {} }; + /** + * Privacy Configuration of the peripheral role. + * + * @note This configuration also apply to the broadcaster role configuration. + */ + struct PeripheralPrivacyConfiguration_t { + /** + * Indicates if non resolvable random address should be used when the + * peripheral advertise non connectable packets. + * + * Resolvable random address continue to be used for connectable packets. + */ + bool use_non_resolvable_random_address; + + /** + * Resolution strategy of initiator resolvable addresses when a + * connection request is received. + */ + enum ResolutionStrategy { + /** + * Do not resolve the address of the initiator and accept the + * connection request. + */ + DO_NOT_RESOLVE, + + /** + * If a bond is present in the secure database and the address + * resolution fail then reject the connection request with the error + * code AUTHENTICATION_FAILLURE. + */ + REJECT_NON_RESOLVED_ADDRESS, + + /** + * Perform the pairing procedure if the initiator resolvable + * address failed the resolution process. + */ + PERFORM_PAIRING_PROCEDURE, + + /** + * Perform the authentication procedure if the initiator resolvable + * address failed the resolution process. + */ + PERFORM_AUTHENTICATION_PROCEDURE + }; + + /** + * Connection strategy to use when a connection request contains a + * private resolvable address. + */ + ResolutionStrategy resolution_strategy; + }; + + /** + * Privacy Configuration of the central role. + * + * @note This configuration encompass the observer role configuration. + */ + struct CentralPrivacyConfiguration_t { + /** + * Indicates if non resolvable random address should be used when the + * central or observer sends scan request packets. + * + * Resolvable random address continue to be used for connection requests. + */ + bool use_non_resolvable_random_address; + + + /** + * Resolution strategy of resolvable addresses received in advertising + * packets. + */ + enum ResolutionStrategy { + /** + * Do not resolve the address received in advertising packets. + */ + DO_NOT_RESOLVE, + + /** + * Resolve the resolvable addresses in the advertising packet and + * forward advertising packet to the application independently of + * the address resolution procedure result. + */ + RESOLVE_AND_FORWARD, + + /** + * Filter out packets containing a resolvable that cannot be resolved + * by this device. + * + * @note Filtering is applied if the local device contains at least + * one bond. + */ + RESOLVE_AND_FILTER + }; + + /** + * Resolution strategy applied to advertising packets received by the + * local device. + */ + ResolutionStrategy resolution_strategy; + }; + /** * Number of microseconds in 1.25 milliseconds. */ @@ -844,8 +989,29 @@ public: * @note Some implementation may refuse to set a new PUBLIC address. * @note Random static address set does not change. * + * @deprecated Starting with mbed-os-5.9.0 this function is deprecated and + * address management is delegated to implementation. Implementations may or + * may not continue to support this function. Compliance with the Bluetooth + * specification and unification of behaviour between implementations are + * the key reasons behind this change: + * - Many implementations does not allow replacement of the public + * address. Therefore programs relying on this function are not portable + * across BLE implementations. + * - The Bluetooth specification forbid replacement of the random static + * address; this address can be set once and only once: at startup. + * Depending on the underlying implementation the random address may or + * may not have been set automatically at startup; therefore update of the + * Random Static address after ble initialisation may be a fault. As a + * result calls to this function were not portable. + * Furthermore replacement of the random static address silently + * invalidates the bond stored in the secure database. + * @return BLE_ERROR_NONE on success. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "Non portable API, use enablePrivacy to enable use of private addresses" + ) virtual ble_error_t setAddress( BLEProtocol::AddressType_t type, const BLEProtocol::AddressBytes_t address @@ -865,6 +1031,9 @@ public: * @param[out] typeP Type of the current address set. * @param[out] address Value of the current address. * + * @note If privacy is enabled the device address may be unavailable to + * application code. + * * @return BLE_ERROR_NONE on success. */ virtual ble_error_t getAddress( @@ -880,6 +1049,22 @@ public: return BLE_ERROR_NOT_IMPLEMENTED; } + /** + * Return the type of a random address. + * + * @param[in] address The random address to retrieve the type from. The # + * address must be ordered in little endian. + * + * @param[out] addressType Type of the address to fill. + * + * @return BLE_ERROR_NONE in case of success or BLE_ERROR_INVALID_PARAM if + * the address in input was not identifiable as a random address. + */ + static ble_error_t getRandomAddressType( + BLEProtocol::AddressBytes_t address, + RandomAddressType_t& addressType + ); + /** * Get the minimum advertising interval in milliseconds, which can be used * for connectable advertising types. @@ -1955,6 +2140,97 @@ public: return BLE_ERROR_NOT_IMPLEMENTED; } + /** + * Enable or disable privacy mode of the local device. + * + * When privacy is enabled, the system use private addresses while it scans, + * advertises or initiate a connection. The device private address is + * renewed every 15 minutes. + * + * @par Configuration + * + * The privacy feature can be configured with the help of the functions + * setPeripheralPrivacyConfiguration and setCentralPrivacyConfiguration + * which respectively set the privacy configuration of the peripheral and + * central role. + * + * @par Default configuration of peripheral role + * + * By default private resolvable address are used for all procedures; + * including advertisement of non connectable packets. Connection request + * from an unknown initiator with a private resolvable address triggers the + * pairing procedure. + * + * @par Default configuration of central role + * + * By default private resolvable address are used for all procedures; + * including active scanning. Address present in advertisement packet are + * resolved and advertisement packets are forwarded to the application + * even if the advertiser private address is unknown. + * + * @param enable[in] Should be set to true to enable the privacy mode and false + * to disable it. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t enablePrivacy(bool enable) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Set the privacy configuration used by the peripheral role. + * + * @param[in] configuration The configuration to set. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t &configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Get the privacy configuration used by the peripheral role. + * + * @param[out] configuration The variable filled with the current + * configuration. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t &configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Set the privacy configuration used by the central role. + * + * @param[in] configuration The configuration to set. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t &configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Get the privacy configuration used by the central role. + * + * @param[out] configuration The variable filled with the current + * configuration. + * + * @return BLE_ERROR_NONE in case of success or an appropriate error code. + */ + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t &configuration + ) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + private: /** * Set the advertising data and scan response in the vendor subsytem. @@ -2285,6 +2561,8 @@ public: * connection. * @param[in] ownAddr Address this device uses for this connection. * @param[in] connectionParams Parameters of the connection. + * @param[in] peerResolvableAddr Resolvable address used by the peer. + * @param[in] localResolvableAddr resolvable address used by the local device. */ void processConnectionEvent( Handle_t handle, @@ -2293,7 +2571,9 @@ public: const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr = NULL, + const uint8_t *localResolvableAddr = NULL ) { /* Update Gap state */ state.advertising = 0; @@ -2307,7 +2587,9 @@ public: peerAddr, ownAddrType, ownAddr, - connectionParams + connectionParams, + peerResolvableAddr, + localResolvableAddr ); connectionCallChain.call(&callbackParams); @@ -2357,7 +2639,7 @@ public: GapAdvertisingParams::AdvertisingType_t type, uint8_t advertisingDataLen, const uint8_t *advertisingData, - BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM_STATIC + BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM ) { // FIXME: remove default parameter for addressType when ST shield is merged; // this has been added to mitigate the lack of dependency management in diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp new file mode 100644 index 0000000000..c25be9fd4e --- /dev/null +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -0,0 +1,36 @@ +/* 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 "ble/Gap.h" + +ble_error_t Gap::getRandomAddressType(BLEProtocol::AddressBytes_t address, RandomAddressType_t& type) +{ + // see section Device address in Bluetooth Link Layer specification + // (Vol 6 - Part B) + switch (address[5] >> 6) { + case 0x03: + type = RandomAddressType_t::STATIC; + return BLE_ERROR_NONE; + case 0x00: + type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE; + return BLE_ERROR_NONE; + case 0x02: + type = RandomAddressType_t::RESOLVABLE_PRIVATE; + return BLE_ERROR_NONE; + default: + return BLE_ERROR_INVALID_PARAM; + } +} From 8643fd55ed7c59459e684cc999dd4a04e9ec108d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 11 Apr 2018 14:22:51 +0100 Subject: [PATCH 092/274] BLE: Add stub for signing API in Nordic pal security manager. --- .../source/nRF5xPalSecurityManager.cpp | 25 +++++++++++++------ .../source/nRF5xPalSecurityManager.h | 18 ++++++++++--- .../TARGET_NRF5/source/nRF5xn.cpp | 12 ++++++--- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index 08acfc4bdb..dfad1a671d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -85,6 +85,7 @@ struct nRF5xSecurityManager::pairing_control_block_t { nRF5xSecurityManager::nRF5xSecurityManager() : ::ble::pal::SecurityManager(), + _sign_counter(), _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), _min_encryption_key_size(7), _max_encryption_key_size(16), @@ -508,12 +509,24 @@ ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) return convert_sd_error(err); } -ble_error_t nRF5xSecurityManager::set_csrk(const csrk_t& csrk) -{ +ble_error_t nRF5xSecurityManager::set_csrk( + const csrk_t& csrk, + sign_count_t sign_counter +) { _csrk = csrk; + _sign_counter = sign_counter; return BLE_ERROR_NONE; } +ble_error_t nRF5xSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + //////////////////////////////////////////////////////////////////////////// // Authentication // @@ -630,23 +643,21 @@ ble_error_t nRF5xSecurityManager::send_keypress_notification( } -ble_error_t nRF5xSecurityManager::generate_secure_connections_oob( - connection_handle_t connection -) { +ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() +{ ble_gap_lesc_p256_pk_t own_secret; ble_gap_lesc_oob_data_t oob_data; memcpy(own_secret.pk, secret.data(), secret.size()); uint32_t err = sd_ble_gap_lesc_oob_data_get( - connection, + BLE_CONN_HANDLE_INVALID, &own_secret, &oob_data ); if (!err) { get_event_handler()->on_secure_connections_oob_generated( - connection, oob_data.r, oob_data.c ); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 31bda5bbcc..35de6ba86b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -237,7 +237,18 @@ public: /** * @see ::ble::pal::SecurityManager::set_csrk */ - virtual ble_error_t set_csrk(const csrk_t &csrk); + virtual ble_error_t set_csrk(const csrk_t &csrk, sign_count_t sign_counter); + + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ); + //////////////////////////////////////////////////////////////////////////// // Authentication @@ -300,9 +311,7 @@ public: /** * @see ::ble::pal::SecurityManager::generate_secure_connections_oob */ - virtual ble_error_t generate_secure_connections_oob( - connection_handle_t connection - ); + virtual ble_error_t generate_secure_connections_oob(); // singleton of nordic Security Manager static nRF5xSecurityManager& get_security_manager(); @@ -312,6 +321,7 @@ public: private: csrk_t _csrk; + sign_count_t _sign_counter; io_capability_t _io_capability; uint8_t _min_encryption_key_size; uint8_t _max_encryption_key_size; 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 75d0e48047..a326fa336c 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 @@ -125,7 +125,7 @@ ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContex return BLE_ERROR_ALREADY_INITIALIZED; } - instanceID = instanceID; + this->instanceID = instanceID; /* ToDo: Clear memory contents, reset the SD, etc. */ if (btle_init() != ERROR_NONE) { @@ -209,11 +209,17 @@ 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(); + ble::pal::vendor::nordic::nRF5xSecurityManager &m_pal = + ble::pal::vendor::nordic::nRF5xSecurityManager::get_security_manager(); + static struct : ble::pal::SigningEventMonitor { + virtual void set_signing_event_handler(EventHandler *signing_event_handler) { } + } dummy_signing_event_monitor; + static ble::generic::GenericSecurityManager m_instance( m_pal, m_db, - const_cast(getGap()) + const_cast(getGap()), + dummy_signing_event_monitor ); return m_instance; From 2811e0086850a3dd5d51316944dddc773256028a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 12 Apr 2018 10:37:13 +0100 Subject: [PATCH 093/274] BLE: Fix Gap privacy related documentation --- features/FEATURE_BLE/ble/Gap.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 095c1c8bc2..c87f82774d 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -360,7 +360,7 @@ public: /** * GAP or GATT failed to authenticate the peer. */ - AUTHENTICATION_FAILLURE = 0x05, + AUTHENTICATION_FAILURE = 0x05, /** * The connection timed out. @@ -783,19 +783,19 @@ public: /** * Privacy Configuration of the peripheral role. * - * @note This configuration also apply to the broadcaster role configuration. + * @note This configuration also applies to the broadcaster role configuration. */ struct PeripheralPrivacyConfiguration_t { /** * Indicates if non resolvable random address should be used when the - * peripheral advertise non connectable packets. + * peripheral advertises non connectable packets. * - * Resolvable random address continue to be used for connectable packets. + * Resolvable random address continues to be used for connectable packets. */ bool use_non_resolvable_random_address; /** - * Resolution strategy of initiator resolvable addresses when a + * Resolution strategy for initiator resolvable addresses when a * connection request is received. */ enum ResolutionStrategy { @@ -835,7 +835,8 @@ public: /** * Privacy Configuration of the central role. * - * @note This configuration encompass the observer role configuration. + * @note This configuration is also used when the local device operates as + * an observer. */ struct CentralPrivacyConfiguration_t { /** @@ -994,9 +995,9 @@ public: * may not continue to support this function. Compliance with the Bluetooth * specification and unification of behaviour between implementations are * the key reasons behind this change: - * - Many implementations does not allow replacement of the public - * address. Therefore programs relying on this function are not portable - * across BLE implementations. + * - Many implementations do not allow changing of the public address. + * Therefore programs relying on this function are not portable across BLE + * implementations. * - The Bluetooth specification forbid replacement of the random static * address; this address can be set once and only once: at startup. * Depending on the underlying implementation the random address may or @@ -1052,7 +1053,7 @@ public: /** * Return the type of a random address. * - * @param[in] address The random address to retrieve the type from. The # + * @param[in] address The random address to retrieve the type from. The * address must be ordered in little endian. * * @param[out] addressType Type of the address to fill. @@ -1062,7 +1063,7 @@ public: */ static ble_error_t getRandomAddressType( BLEProtocol::AddressBytes_t address, - RandomAddressType_t& addressType + RandomAddressType_t* addressType ); /** @@ -2156,20 +2157,20 @@ public: * * @par Default configuration of peripheral role * - * By default private resolvable address are used for all procedures; + * By default private resolvable addresses are used for all procedures; * including advertisement of non connectable packets. Connection request * from an unknown initiator with a private resolvable address triggers the * pairing procedure. * * @par Default configuration of central role * - * By default private resolvable address are used for all procedures; - * including active scanning. Address present in advertisement packet are + * By default private resolvable addresses are used for all procedures; + * including active scanning. Addresses present in advertisement packet are * resolved and advertisement packets are forwarded to the application * even if the advertiser private address is unknown. * - * @param enable[in] Should be set to true to enable the privacy mode and false - * to disable it. + * @param enable[in] Should be set to true to enable the privacy mode and + * false to disable it. * * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ From 90c85955ad1615a3c9584e9519d60b35dc19fe56 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 12 Apr 2018 11:04:44 +0100 Subject: [PATCH 094/274] BLE: Fix GAP privacy related signatures. --- features/FEATURE_BLE/ble/Gap.h | 8 ++++---- features/FEATURE_BLE/source/Gap.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index c87f82774d..17abea4441 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -2186,7 +2186,7 @@ public: * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ virtual ble_error_t setPeripheralPrivacyConfiguration( - const PeripheralPrivacyConfiguration_t &configuration + const PeripheralPrivacyConfiguration_t *configuration ) { return BLE_ERROR_NOT_IMPLEMENTED; } @@ -2200,7 +2200,7 @@ public: * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ virtual ble_error_t getPeripheralPrivacyConfiguration( - PeripheralPrivacyConfiguration_t &configuration + PeripheralPrivacyConfiguration_t *configuration ) { return BLE_ERROR_NOT_IMPLEMENTED; } @@ -2213,7 +2213,7 @@ public: * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ virtual ble_error_t setCentralPrivacyConfiguration( - const CentralPrivacyConfiguration_t &configuration + const CentralPrivacyConfiguration_t *configuration ) { return BLE_ERROR_NOT_IMPLEMENTED; } @@ -2227,7 +2227,7 @@ public: * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ virtual ble_error_t getCentralPrivacyConfiguration( - CentralPrivacyConfiguration_t &configuration + CentralPrivacyConfiguration_t *configuration ) { return BLE_ERROR_NOT_IMPLEMENTED; } diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index c25be9fd4e..3793c0c46c 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -16,8 +16,10 @@ #include "ble/Gap.h" -ble_error_t Gap::getRandomAddressType(BLEProtocol::AddressBytes_t address, RandomAddressType_t& type) -{ +ble_error_t Gap::getRandomAddressType( + BLEProtocol::AddressBytes_t address, + RandomAddressType_t* type +) { // see section Device address in Bluetooth Link Layer specification // (Vol 6 - Part B) switch (address[5] >> 6) { From 6b67a6d0a6d8f9acece4fb8a65f592bf92a7de68 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 16 Apr 2018 15:06:37 +0100 Subject: [PATCH 095/274] missing deref after signature change --- features/FEATURE_BLE/source/Gap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index 3793c0c46c..7643a34733 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -24,13 +24,13 @@ ble_error_t Gap::getRandomAddressType( // (Vol 6 - Part B) switch (address[5] >> 6) { case 0x03: - type = RandomAddressType_t::STATIC; + *type = RandomAddressType_t::STATIC; return BLE_ERROR_NONE; case 0x00: - type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE; + *type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE; return BLE_ERROR_NONE; case 0x02: - type = RandomAddressType_t::RESOLVABLE_PRIVATE; + *type = RandomAddressType_t::RESOLVABLE_PRIVATE; return BLE_ERROR_NONE; default: return BLE_ERROR_INVALID_PARAM; From 12899b1e09afdd15d3d4edddb51ceec0c9a6d143 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 16 Apr 2018 15:34:15 +0100 Subject: [PATCH 096/274] fix const induced recursive call --- .../FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index d624dcbff4..2a26fa27fb 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -166,7 +166,8 @@ const char* BLE::getVersion() generic::GenericGap& BLE::getGap() { - return const_cast(getGap()); + const BLE &const_self = const_cast(*this); + return const_cast(const_self.getGap()); } const generic::GenericGap& BLE::getGap() const @@ -204,7 +205,8 @@ generic::GenericGattClient& BLE::getGattClient() SecurityManager& BLE::getSecurityManager() { - return const_cast(getSecurityManager()); + const BLE &const_self = const_cast(*this); + return const_cast(const_self.getSecurityManager()); } const SecurityManager& BLE::getSecurityManager() const From 9a9167602d40ad2b8e329478b7e6699a16f9b8de Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 16 Apr 2018 15:58:03 +0100 Subject: [PATCH 097/274] moved init code into non-const for clarity --- .../TARGET_CORDIO/source/CordioBLE.cpp | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 2a26fa27fb..46ec738a0e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -166,21 +166,20 @@ const char* BLE::getVersion() generic::GenericGap& BLE::getGap() { - const BLE &const_self = const_cast(*this); - return const_cast(const_self.getGap()); + static pal::vendor::cordio::GenericAccessService cordio_gap_service; + static ble::generic::GenericGap gap( + _event_queue, + pal::vendor::cordio::Gap::get_gap(), + cordio_gap_service + ); + + return gap; } const generic::GenericGap& BLE::getGap() const { - static pal::vendor::cordio::Gap& cordio_pal_gap = - pal::vendor::cordio::Gap::get_gap(); - static pal::vendor::cordio::GenericAccessService cordio_gap_service; - static ble::generic::GenericGap gap( - _event_queue, - cordio_pal_gap, - cordio_gap_service - ); - return gap; + BLE &self = const_cast(*this); + return const_cast(self.getGap()); }; GattServer& BLE::getGattServer() @@ -204,30 +203,25 @@ generic::GenericGattClient& BLE::getGattClient() } SecurityManager& BLE::getSecurityManager() -{ - const BLE &const_self = const_cast(*this); - return const_cast(const_self.getSecurityManager()); -} - -const SecurityManager& BLE::getSecurityManager() const { static pal::MemorySecurityDb m_db; - pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); - - BLE &self = const_cast(*this); - - static SigningEventMonitorProxy signing_event_monitor(self); - + static SigningEventMonitorProxy signing_event_monitor(*this); static generic::GenericSecurityManager m_instance( - m_pal, + pal::vendor::cordio::CordioSecurityManager::get_security_manager(), m_db, - self.getGap(), + getGap(), signing_event_monitor ); return m_instance; } +const SecurityManager& BLE::getSecurityManager() const +{ + const BLE &self = const_cast(*this); + return const_cast(self.getSecurityManager()); +} + void BLE::waitForEvent() { static Timeout nextTimeout; From a7f2384e109a7e7e6451ccbebaa3c0316ee504de Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 16:52:05 +0100 Subject: [PATCH 098/274] BLE: Add default privacy configuration --- features/FEATURE_BLE/ble/Gap.h | 6 ++++++ features/FEATURE_BLE/source/Gap.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 17abea4441..148f36edc4 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -887,6 +887,12 @@ public: */ static const uint16_t UNIT_1_25_MS = 1250; + static const PeripheralPrivacyConfiguration_t + default_peripheral_privacy_configuration; + + static const CentralPrivacyConfiguration_t + default_central_privacy_configuration; + /** * Convert milliseconds into 1.25ms units. * diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index 7643a34733..c8650f27c7 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -36,3 +36,13 @@ ble_error_t Gap::getRandomAddressType( return BLE_ERROR_INVALID_PARAM; } } + +const Gap::PeripheralPrivacyConfiguration_t Gap::default_peripheral_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE +}; + +const Gap::CentralPrivacyConfiguration_t Gap::default_central_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ CentralPrivacyConfiguration_t::DO_NOT_RESOLVE +}; From 365f3d25275c1bd4fbcc59bf5ee1e925df1362de Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 16:53:31 +0100 Subject: [PATCH 099/274] BLE: Add ah in Nordic CryptoToolbox. --- .../TARGET_NRF5/source/nRF5XCrypto.cpp | 32 +++++++++++++++++ .../TARGET_NRF5/source/nRF5xCrypto.h | 34 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp index ca875d805f..090b29db62 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp @@ -37,6 +37,8 @@ #include "cmsis.h" #include "nRF5xCrypto.h" #include "platform/mbed_assert.h" +#include "nrf_soc.h" + namespace ble { namespace pal { @@ -128,6 +130,36 @@ bool CryptoToolbox::generate_shared_secret( return err ? false : true; } +bool CryptoToolbox::ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash +) { + // Note copy then swap operation can be optimized. + + // Note: the encryption block works in big endian; go figure. + nrf_ecb_hal_data_t ecb_hal_data; + + memcpy(ecb_hal_data.key, irk.data(), irk.size()); + swap_endian(ecb_hal_data.key, sizeof(ecb_hal_data.key)); + + memcpy(ecb_hal_data.cleartext, prand.data(), prand.size()); + memset(ecb_hal_data.cleartext + prand.size(), 0, sizeof(ecb_hal_data.cleartext) - prand.size()); + swap_endian(ecb_hal_data.cleartext, sizeof(ecb_hal_data.cleartext)); + + uint32_t err = sd_ecb_block_encrypt(&ecb_hal_data); + + if (err) { + return false; + } + + swap_endian(ecb_hal_data.ciphertext, sizeof(ecb_hal_data.ciphertext)); + + memcpy(hash.data(), ecb_hal_data.ciphertext, hash.size()); + + return true; +} + void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { ble::public_key_coord_t src_be = src.data(); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index 0189e44ddc..470002c7e1 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -48,6 +48,21 @@ public: */ static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; + /** + * Size of an IRK. + */ + static const ptrdiff_t irk_size_ = irk_t::size_; + + /** + * Size of the hash generated by ah. + */ + static const ptrdiff_t hash_size_ = 3; + + /** + * Size of prand. + */ + static const ptrdiff_t prand_size_ = 3; + /** * Create a new CryptoToolbox. */ @@ -88,6 +103,25 @@ public: ArrayView shared_secret ); + /** + * Execute the function ah. This function can be used to generate private + * resolvable addresses and resolve them. + * + * @note all parameters passed and return by this fucntion are in little + * endian. + * + * @param[in] irk The key used to create hash. + * @param[in] prand The random part from which the hash will be generated. + * @param[out] hash The hash generated. + * + * @return true in case of success and false otherwise. + */ + bool ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash + ); + private: void load_mpi(mbedtls_mpi& dest, const ArrayView& src); From fb680db62177a1bba223a9fba6b11af0b806edbc Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 16:57:07 +0100 Subject: [PATCH 100/274] BLE: Implement resolving list in Nordic PAL security manager --- .../source/nRF5xPalSecurityManager.cpp | 91 +++++++++++++++++-- .../source/nRF5xPalSecurityManager.h | 45 +++++++++ 2 files changed, 127 insertions(+), 9 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index dfad1a671d..ad35e29aeb 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -89,7 +89,8 @@ nRF5xSecurityManager::nRF5xSecurityManager() _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), _min_encryption_key_size(7), _max_encryption_key_size(16), - _control_blocks(NULL) + _control_blocks(NULL), + resolving_list_entry_count(0) { } @@ -141,8 +142,7 @@ ble_error_t nRF5xSecurityManager::reset() uint8_t nRF5xSecurityManager::read_resolving_list_capacity() { - // FIXME: implement with privacy - return 0; + return MAX_RESOLVING_LIST_ENTRIES; } ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( @@ -150,22 +150,95 @@ ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( const address_t &peer_identity_address, const irk_t &peer_irk ) { - // FIXME: implement with privacy - return BLE_ERROR_NOT_IMPLEMENTED; + if (resolving_list_entry_count >= MAX_RESOLVING_LIST_ENTRIES) { + return BLE_ERROR_INVALID_STATE; + } + + resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count]; + entry.peer_identity_address_type = peer_identity_address_type; + entry.peer_identity_address = peer_identity_address; + entry.peer_irk = peer_irk; + + ++resolving_list_entry_count; + + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address ) { - // FIXME: implement with privacy - return BLE_ERROR_NOT_IMPLEMENTED; + size_t entry_index; + + // first the index needs to be found + for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) { + resolving_list_entry_t& entry = resolving_list[entry_index]; + if (entry.peer_identity_address_type == peer_identity_address_type && + entry.peer_identity_address == peer_identity_address + ) { + break; + } + } + + if (entry_index == resolving_list_entry_count) { + return BLE_ERROR_INVALID_PARAM; + } + + // Elements after the entry can be moved in the list + for (size_t i = entry_index; i < (resolving_list_entry_count - 1); ++i) { + resolving_list[i] = resolving_list[i + 1]; + } + + --resolving_list_entry_count; + + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::clear_resolving_list() { - // FIXME: implement with privacy - return BLE_ERROR_NOT_IMPLEMENTED; + resolving_list_entry_count = 0; + return BLE_ERROR_NONE; +} + +void nRF5xSecurityManager::get_resolving_list( + size_t& count, + const resolving_list_entry_t*& entries +) { + count = resolving_list_entry_count; + entries = resolving_list; +} + +bool nRF5xSecurityManager::resolve_address( + const address_t& resolvable_address, + advertising_peer_address_type_t& resolved_address_type, + address_t& resolved_address +) { + typedef byte_array_t hash_t; + + for (size_t i = 0; i < resolving_list_entry_count; ++i) { + resolving_list_entry_t& entry = resolving_list[i]; + hash_t hash_generated; + + // Compute the hash part from the random address part when the irk of + // the entry is used + _crypto.ah( + make_const_ArrayView(entry.peer_irk), + make_const_ArrayView( + resolvable_address.data() + CryptoToolbox::hash_size_ + ), + make_ArrayView(hash_generated) + ); + + // Compare hash generated with the hash present in the address passed as + // parameter. If they are equal then the IRK of the entry has been used + // to generate the resolvable address. + if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) { + resolved_address_type = entry.peer_identity_address_type; + resolved_address = entry.peer_identity_address; + return true; + } + } + return false; } //////////////////////////////////////////////////////////////////////////// diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 35de6ba86b..443fa19130 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -83,6 +83,46 @@ public: */ virtual ble_error_t clear_resolving_list(); + /** + * An entry of the resolving list stored in the SecurityManager. + */ + struct resolving_list_entry_t { + resolving_list_entry_t() : + peer_identity_address_type( + advertising_peer_address_type_t::PUBLIC_ADDRESS + ) + { } + + irk_t peer_irk; + address_t peer_identity_address; + advertising_peer_address_type_t peer_identity_address_type; + }; + + /** + * Return the IRKs present in the resolving list + * @param count The number of entries present in the resolving list. + * @param pointer to the first entry of the resolving list. + */ + void get_resolving_list( + size_t& count, + const resolving_list_entry_t*& entries + ); + + /** + * Try to resolve a private resolvable address. + * + * @param resolvable_address The address to resolve. + * @param resolved_address_type The type of the identity address resolved. + * @param resolved_address The identity address resolved. + * @return True if the address has been resolved and false otherwise. + */ + bool resolve_address( + const address_t& resolvable_address, + advertising_peer_address_type_t& resolved_address_type, + address_t& resolved_address + ); + + //////////////////////////////////////////////////////////////////////////// // Pairing // @@ -351,6 +391,11 @@ private: ble::public_key_coord_t X; ble::public_key_coord_t Y; ble::public_key_coord_t secret; + + static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_WHITELIST_IRK_MAX_COUNT; + + size_t resolving_list_entry_count; + resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; }; } // nordic From a18283d897749a776bd3763b04e06884aed1bac4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 18:15:32 +0100 Subject: [PATCH 101/274] BLE: change nRF5xSecurityManager::get_resolving_list return It now returns a resolving list entry. --- .../TARGET_NRF5/source/nRF5xPalSecurityManager.cpp | 12 ++++++------ .../TARGET_NRF5/source/nRF5xPalSecurityManager.h | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index ad35e29aeb..e63345900e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -200,12 +200,12 @@ ble_error_t nRF5xSecurityManager::clear_resolving_list() return BLE_ERROR_NONE; } -void nRF5xSecurityManager::get_resolving_list( - size_t& count, - const resolving_list_entry_t*& entries -) { - count = resolving_list_entry_count; - entries = resolving_list; +ArrayView +nRF5xSecurityManager::get_resolving_list() { + return ArrayView( + resolving_list, + resolving_list_entry_count + ); } bool nRF5xSecurityManager::resolve_address( diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 443fa19130..d358af79b2 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -103,10 +103,7 @@ public: * @param count The number of entries present in the resolving list. * @param pointer to the first entry of the resolving list. */ - void get_resolving_list( - size_t& count, - const resolving_list_entry_t*& entries - ); + ArrayView get_resolving_list(); /** * Try to resolve a private resolvable address. From 2a9d80c5f04f782c9b97b58b85ab559c5445c133 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 18:16:36 +0100 Subject: [PATCH 102/274] BLE: Change nRF5xSecurityManager::resolve_address signature Return the resolving list entry instead of accepting in parameters. --- .../source/nRF5xPalSecurityManager.cpp | 15 ++++++--------- .../TARGET_NRF5/source/nRF5xPalSecurityManager.h | 11 ++++------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index e63345900e..fec4ff6885 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -208,11 +208,8 @@ nRF5xSecurityManager::get_resolving_list() { ); } -bool nRF5xSecurityManager::resolve_address( - const address_t& resolvable_address, - advertising_peer_address_type_t& resolved_address_type, - address_t& resolved_address -) { +const nRF5xSecurityManager::resolving_list_entry_t* +nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { typedef byte_array_t hash_t; for (size_t i = 0; i < resolving_list_entry_count; ++i) { @@ -233,14 +230,14 @@ bool nRF5xSecurityManager::resolve_address( // parameter. If they are equal then the IRK of the entry has been used // to generate the resolvable address. if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) { - resolved_address_type = entry.peer_identity_address_type; - resolved_address = entry.peer_identity_address; - return true; + return &entry; } } - return false; + return NULL; } + + //////////////////////////////////////////////////////////////////////////// // Pairing // diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index d358af79b2..bd9206b790 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -109,14 +109,11 @@ public: * Try to resolve a private resolvable address. * * @param resolvable_address The address to resolve. - * @param resolved_address_type The type of the identity address resolved. - * @param resolved_address The identity address resolved. - * @return True if the address has been resolved and false otherwise. + * + * @return Pointer to the entry found if any. */ - bool resolve_address( - const address_t& resolvable_address, - advertising_peer_address_type_t& resolved_address_type, - address_t& resolved_address + const resolving_list_entry_t* resolve_address( + const address_t& resolvable_address ); From b3c871c9602268ea7d581a0ef91e9dad1dee0cab Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 16 Apr 2018 18:17:17 +0100 Subject: [PATCH 103/274] BLE: Implement privacy on Nordic targets. --- .../TARGET_NRF5/source/btle/btle.cpp | 52 +-- .../TARGET_NRF5/source/nRF5xGap.cpp | 432 +++++++++++++++--- .../TARGET_NRF5/source/nRF5xGap.h | 45 +- 3 files changed, 397 insertions(+), 132 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp index 32e1e3df0c..8839fd19db 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp @@ -61,7 +61,7 @@ void app_error_handler(uint32_t error_code, uint32_t line_num, const extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector. -static void btle_handler(ble_evt_t *p_ble_evt); +void btle_handler(ble_evt_t *p_ble_evt); static void sys_evt_dispatch(uint32_t sys_evt) { @@ -161,7 +161,7 @@ error_t btle_init(void) return btle_gap_init(); } -static void btle_handler(ble_evt_t *p_ble_evt) +void btle_handler(ble_evt_t *p_ble_evt) { using ble::pal::vendor::nordic::nRF5XGattClient; using ble::pal::vendor::nordic::nRF5xSecurityManager; @@ -189,38 +189,12 @@ static void btle_handler(ble_evt_t *p_ble_evt) /* Custom event handler */ switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; -#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110) - /* Only peripheral role is supported by S110 */ - Gap::Role_t role = Gap::PERIPHERAL; -#else - Gap::Role_t role = static_cast(p_ble_evt->evt.gap_evt.params.connected.role); -#endif - gap.setConnectionHandle(handle); - const Gap::ConnectionParams_t *params = reinterpret_cast(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); - const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; -#if (NRF_SD_BLE_API_VERSION <= 2) - const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - static_cast(own->addr_type), own->addr, - params); -#else - Gap::AddressType_t addr_type; - Gap::Address_t own_address; - gap.getAddress(&addr_type, own_address); - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - addr_type, own_address, - params); -#endif + case BLE_GAP_EVT_CONNECTED: + gap.on_connection( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.connected + ); break; - } case BLE_GAP_EVT_DISCONNECTED: { Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; @@ -266,17 +240,9 @@ static void btle_handler(ble_evt_t *p_ble_evt) // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; - case BLE_GAP_EVT_ADV_REPORT: { - const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - gap.processAdvertisementReport(advReport->peer_addr.addr, - advReport->rssi, - advReport->scan_rsp, - static_cast(advReport->type), - advReport->dlen, - advReport->data, - static_cast(advReport->peer_addr.addr_type)); + case BLE_GAP_EVT_ADV_REPORT: + gap.on_advertising_packet(p_ble_evt->evt.gap_evt.params.adv_report); break; - } default: break; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index bb38334b59..3d3c085adc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -26,7 +26,66 @@ #include "ble_advdata.h" #include "headers/nrf_ble_hci.h" #include "ble/pal/ConnectionEventMonitor.h" +#include "nRF5XPalSecurityManager.h" +using ble::pal::vendor::nordic::nRF5xSecurityManager; +typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; +using ble::ArrayView; +using ble::pal::advertising_peer_address_type_t; + +namespace { + +nRF5xSecurityManager& get_sm() { + return nRF5xSecurityManager::get_security_manager(); +} + +void set_private_resolvable_address() { + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE }; + sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); +} + +void set_private_non_resolvable_address() { + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; + sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); +} + +bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { + switch (params.getAdvertisingType()) { + case GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED: + case GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED: + return true; + default: + return false; + } +} + +bool is_identity_address(BLEProtocol::AddressType_t address_type) { + switch (address_type) { + case BLEProtocol::AddressType::PUBLIC_IDENTITY: + case BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY: + return true; + default: + return false; + } +} + +BLEProtocol::AddressType_t convert_nordic_address(uint8_t address) { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return BLEProtocol::AddressType::PUBLIC; + } else { + return BLEProtocol::AddressType::RANDOM; + } +} + +BLEProtocol::AddressType_t convert_identity_address(advertising_peer_address_type_t address) { + if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { + return BLEProtocol::AddressType::PUBLIC_IDENTITY; + } else { + return BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY; + } +} + +} // namespace void radioNotificationStaticCallback(bool param) { nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); @@ -40,7 +99,11 @@ nRF5xGap::nRF5xGap() : Gap(), whitelistAddresses(), radioNotificationCallbackParam(false), radioNotificationTimeout(), - _connection_event_handler(NULL) + _connection_event_handler(NULL), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), + _non_private_type(BLEProtocol::AddressType::RANDOM) { m_connectionHandle = BLE_CONN_HANDLE_INVALID; } @@ -204,6 +267,29 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) } } + if (_privacy_enabled) { + if (_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + } + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } + adv_para.p_whitelist = &whitelist; #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -255,6 +341,8 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) } } + // FIXME: fill the irk list once addresses are resolved by the softdevice. + scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else @@ -270,6 +358,14 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + if (_privacy_enabled) { + if (_central_privacy_configuration.use_non_resolvable_random_address) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } + if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -318,6 +414,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, const GapScanningParams *scanParamsIn) { ble_gap_addr_t addr; + ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); @@ -354,9 +451,37 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, return error; } } - scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ + + if (_privacy_enabled) { + // configure the "whitelist" with the IRK associated with the identity + // address in input. + if (is_identity_address(peerAddrType)) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t i; + for (i = 0; i < entries.size(); ++i) { + const ble::address_t& entry_address = entries[i].peer_identity_address; + + // entry found; fill the whitelist and invalidate addr_ptr + if (memcmp(entry_address.data(), peerAddr, entry_address.size_) == 0) { + whitelist.pp_irks[0] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + whitelist.irk_count = 1; + scanParams.selective = 1; + addr_ptr = NULL; + break; + } + } + + // Occur only if the address in input hasn't been resolved. + if (i == entries.size()) { + return BLE_ERROR_INVALID_PARAM; + } + } + + set_private_resolvable_address(); + } #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -388,7 +513,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, scanParams.timeout = _scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ } - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams); if (rc == NRF_SUCCESS) { return BLE_ERROR_NONE; } @@ -543,52 +668,33 @@ uint16_t nRF5xGap::getConnectionHandle(void) /**************************************************************************/ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) { -#if (NRF_SD_BLE_API_VERSION <= 2) - uint8_t cycle_mode; -#else - ble_gap_privacy_params_t privacy_params = {0}; -#endif + using BLEProtocol::AddressType; + if (type != AddressType::PUBLIC || type != AddressType::RANDOM_STATIC) { + return BLE_ERROR_INVALID_PARAM; + } + + if (_privacy_enabled) { + return BLE_ERROR_INVALID_STATE; + } ble_gap_addr_t dev_addr; + memcpy(dev_addr.addr, address, ADDR_LEN); + if (type == AddressType::PUBLIC) { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + } else { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; + } - /* When using Public or Static addresses, the cycle mode must be None. - When using Random Private addresses, the cycle mode must be Auto. - In auto mode, the given address is ignored. - */ - if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) - { - memcpy(dev_addr.addr, address, ADDR_LEN); #if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; + ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); #else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - dev_addr.addr_type = type; + // FIXME is there any reason to use the pm ? + ble_gap_privacy_params_t privacy_params = {0}; + privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - } - else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) - { -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; -#else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - privacy_params.private_addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - // address is ignored when in auto mode - } - else - { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - dev_addr.addr_type = type; - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); #endif return BLE_ERROR_NONE; @@ -597,6 +703,7 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) { ble_gap_addr_t dev_addr; + #if (NRF_SD_BLE_API_VERSION <= 2) if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { #else @@ -606,11 +713,17 @@ ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) } if (typeP != NULL) { - *typeP = static_cast(dev_addr.addr_type); + if (dev_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC){ + *typeP = BLEProtocol::AddressType::PUBLIC; + } else { + *typeP = BLEProtocol::AddressType::RANDOM; + } } + if (address != NULL) { memcpy(address, dev_addr.addr, ADDR_LEN); } + return BLE_ERROR_NONE; } @@ -939,6 +1052,55 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } +ble_error_t nRF5xGap::enablePrivacy(bool enable) +{ + if (enable == _privacy_enabled) { + return BLE_ERROR_NONE; + } + + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (enable == false) { + err = setAddress(_non_private_type, _non_private_address); + } else { + err = getAddress(&_non_private_type, _non_private_address); + } + + if (err) { + return err; + } + + _privacy_enabled = enable; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) { + _peripheral_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) { + *configuration = _peripheral_privacy_configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) { + _central_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) { + *configuration = _central_privacy_configuration; + return BLE_ERROR_NONE; +} + #if (NRF_SD_BLE_API_VERSION <= 2) /**************************************************************************/ /*! @@ -1055,38 +1217,6 @@ void nRF5xGap::set_connection_event_handler( _connection_event_handler = connection_event_handler; } -void nRF5xGap::processConnectionEvent( - Handle_t handle, - Role_t role, - BLEProtocol::AddressType_t peerAddrType, - const BLEProtocol::AddressBytes_t peerAddr, - BLEProtocol::AddressType_t ownAddrType, - const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams -) { - if (_connection_event_handler) { - _connection_event_handler->on_connected( - handle, - role, - peerAddrType, - peerAddr, - ownAddrType, - ownAddr, - connectionParams - ); - } - - ::Gap::processConnectionEvent( - handle, - role, - peerAddrType, - peerAddr, - ownAddrType, - ownAddr, - connectionParams - ); -} - void nRF5xGap::processDisconnectionEvent( Handle_t handle, DisconnectionReason_t reason @@ -1103,3 +1233,155 @@ void nRF5xGap::processDisconnectionEvent( reason ); } + +void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { + using BLEProtocol::AddressType; + + // set the new connection handle as the _default_ handle in gap + setConnectionHandle(handle); + + // deal with own address + AddressType_t own_addr_type; + Address_t own_address; + const uint8_t* own_resolvable_address = NULL; + +#if (NRF_SD_BLE_API_VERSION <= 2) + if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { + own_addr_type = AddressType::PUBLIC; + } else { + own_addr_type = AddressType::RANDOM; + } + memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); +#else + gap.getAddress(&addr_type, own_address); +#endif + + if (_privacy_enabled) { + own_resolvable_address = own_address; + } + + // deal with the peer address: If privacy is enabled then the softdevice + // indicates if the address has been resolved or not. If the address has + // been resolved then the identity address should be passed to the application. + // Depending on the privacy chosen by the application, connection request + // from privacy enabled peers may trigger a disconnection, the pairing procedure + // or the authentication procedure. + AddressType_t peer_addr_type; + const uint8_t* peer_address; + const uint8_t* peer_resolvable_address; + + if (evt.irk_match) { + const resolving_list_entry_t* entry = get_sm().resolve_address( + evt.peer_addr.addr + ); + MBED_ASSERT(entry == NULL); + + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + peer_address = entry->peer_identity_address.data(); + peer_resolvable_address = evt.peer_addr.addr; + } else { + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + get_sm().get_resolving_list().size() > 0 + ) { + // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible + // with the softdevice ... + sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + return; + } + + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + peer_address = evt.peer_addr.addr; + peer_resolvable_address = NULL; + } + + // notify internal event handler before applying the resolution strategy + if (_connection_event_handler) { + _connection_event_handler->on_connected( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)) + ); + } + + // Apply authentication strategy before application notification + if (!evt.irk_match && + _privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + ) { + switch (_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle); + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + // FIXME: lookup secure DB to know what to do. + break; + + default: + break; + } + } + + processConnectionEvent( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)), + peer_resolvable_address, + own_resolvable_address + ); +} + +void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { + using BLEProtocol::AddressType; + + AddressType_t peer_addr_type; + const uint8_t* peer_address = evt.peer_addr.addr; + + if (_privacy_enabled && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE + ) { + using ble::pal::vendor::nordic::nRF5xSecurityManager; + + const resolving_list_entry_t* entry = get_sm().resolve_address( + peer_address + ); + + if (entry) { + peer_address = entry->peer_identity_address.data(); + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + } else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } else { + // filter out the packet. + return; + } + } else { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } + + processAdvertisementReport( + peer_address, + evt.rssi, + evt.scan_rsp, + static_cast(evt.type), + evt.dlen, + evt.data, + peer_addr_type + ); +} + + + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h index 9a6973331c..cb12a610f2 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.h @@ -122,6 +122,24 @@ public: return BLE_ERROR_UNSPECIFIED; } + virtual ble_error_t enablePrivacy(bool enable); + + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); + /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); @@ -260,23 +278,10 @@ public: /** @note Implements ConnectionEventMonitor. * @copydoc ConnectionEventMonitor::set_connection_event_handler */ - void set_connection_event_handler( + virtual void set_connection_event_handler( ConnectionEventMonitor::EventHandler* connection_event_handler ); - /** - * @copydoc ::Gap::processConnectionEvent - */ - void processConnectionEvent( - Handle_t handle, - Role_t role, - BLEProtocol::AddressType_t peerAddrType, - const BLEProtocol::AddressBytes_t peerAddr, - BLEProtocol::AddressType_t ownAddrType, - const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams - ); - /** * @copydoc ::Gap::processDisconnectionEvent */ @@ -285,10 +290,22 @@ public: DisconnectionReason_t reason ); +private: + friend void btle_handler(ble_evt_t *p_ble_evt); + + void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt); + void on_advertising_packet(const ble_gap_evt_adv_report_t &evt); + uint16_t m_connectionHandle; ConnectionEventMonitor::EventHandler* _connection_event_handler; + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + AddressType_t _non_private_type; + Address_t _non_private_address; + /* * Allow instantiation from nRF5xn when required. */ From 51e1c76b4ab004b26749061f6aa550ad8fb3138d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:03:20 +0100 Subject: [PATCH 104/274] BLE: Set default mac address to all 00. --- features/FEATURE_BLE/ble/BLETypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 41e4c99f13..0c4c894eb3 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -426,10 +426,10 @@ typedef uint32_t sign_count_t; */ struct address_t : public byte_array_t<6> { /** - * Create an invalid mac address, equal to FF:FF:FF:FF:FF:FF + * Create an invalid mac address, equal to 00:00:00:00:00:00 */ address_t() { - memset(_value, 0xFF, sizeof(_value)); + memset(_value, 0x00, sizeof(_value)); } /** From dfbf383614872d0eaafd646601344aec70c91eb0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:03:57 +0100 Subject: [PATCH 105/274] BLE: Fix const correctness of ::Gap::getRandomAddressType --- features/FEATURE_BLE/ble/Gap.h | 2 +- features/FEATURE_BLE/source/Gap.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 148f36edc4..adaf06bc44 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -1068,7 +1068,7 @@ public: * the address in input was not identifiable as a random address. */ static ble_error_t getRandomAddressType( - BLEProtocol::AddressBytes_t address, + const BLEProtocol::AddressBytes_t address, RandomAddressType_t* addressType ); diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index c8650f27c7..425f833106 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -17,7 +17,7 @@ #include "ble/Gap.h" ble_error_t Gap::getRandomAddressType( - BLEProtocol::AddressBytes_t address, + const BLEProtocol::AddressBytes_t address, RandomAddressType_t* type ) { // see section Device address in Bluetooth Link Layer specification From 9643b571592f36b48346b874dfa4e59dec2ad1ce Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:06:00 +0100 Subject: [PATCH 106/274] BLE: Remove flag SecurityDistributionFlags_t::local_address_is_public This flag was not used and not useful. --- features/FEATURE_BLE/ble/pal/SecurityDb.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 62f67fb95b..2de7734546 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -35,7 +35,6 @@ struct SecurityDistributionFlags_t { peer_address(), encryption_key_size(0), peer_address_is_public(false), - local_address_is_public(false), csrk_stored(false), csrk_mitm_protected(false), ltk_stored(false), @@ -50,8 +49,6 @@ struct SecurityDistributionFlags_t { uint8_t encryption_key_size; /** true if peer address is public, false if it's static random */ uint8_t peer_address_is_public:1; - /** true if local address is public, false if it's static random */ - uint8_t local_address_is_public:1; /** CSRK (Connection Signature Resolving Key) has been distributed and stored */ uint8_t csrk_stored:1; From ab6821aab86610fc471ac91af92478cf4bf733b3 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:06:47 +0100 Subject: [PATCH 107/274] BLE: Add a flag indicating if irk is stored in the distribution flags. --- features/FEATURE_BLE/ble/pal/SecurityDb.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 2de7734546..023fd0bcac 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -39,7 +39,8 @@ struct SecurityDistributionFlags_t { csrk_mitm_protected(false), ltk_stored(false), ltk_mitm_protected(false), - secure_connections_paired(false) { + secure_connections_paired(false), + irk_stored(false) { } /** peer address */ @@ -60,6 +61,8 @@ struct SecurityDistributionFlags_t { 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; }; /** Long Term Key and data used to identify it */ From e8041510a63ac1d217d79f5978c00d6c1a8acb83 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:07:19 +0100 Subject: [PATCH 108/274] BLE: Add a flag that indicate if the identity address is public or not. --- features/FEATURE_BLE/ble/pal/SecurityDb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 023fd0bcac..653ec57dec 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -81,6 +81,8 @@ struct SecurityEntryIdentity_t { address_t identity_address; /** Identity Resolving Key */ irk_t irk; + /** true if peer identity address is public, false if it's static random */ + uint8_t identity_address_is_public:1; }; /** From 15fa3bfd37a66c9decfa659701ae4becd3871a47 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:08:01 +0100 Subject: [PATCH 109/274] BLE: Add a function to retrieve a device identity. --- features/FEATURE_BLE/ble/pal/SecurityDb.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 653ec57dec..7c6e77637e 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -105,6 +105,8 @@ public: SecurityEntryKeysDbCb_t; typedef mbed::Callback SecurityEntryCsrkDbCb_t; + typedef mbed::Callback + SecurityEntryIdentityDbCb_t; typedef mbed::Callback WhitelistDbCb_t; @@ -261,6 +263,17 @@ public: const address_t &peer_address ) = 0; + /** + * 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. + */ + virtual void get_entry_identity( + SecurityEntryIdentityDbCb_t cb, + entry_handle_t db_entry + ) = 0; + /** * Update peer signing key. * From 6fc74fbc4464b5a94417c8b35ea00e9fe295b1e4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:09:00 +0100 Subject: [PATCH 110/274] BLE: Fix MemorySecurityDB constructor warning. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index eb28867734..fc80e4cc45 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -49,8 +49,9 @@ private: } public: - MemorySecurityDb() { }; - virtual ~MemorySecurityDb() { }; + MemorySecurityDb() : _local_sign_counter(0) { } + + virtual ~MemorySecurityDb() { } virtual const SecurityDistributionFlags_t* get_distribution_flags( entry_handle_t entry_handle From 06e0aa3440b6183fd57a74eb0615abf1bb9a1074 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:10:19 +0100 Subject: [PATCH 111/274] BLE: flag that irk has been stored in the security entry. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index fc80e4cc45..f71c95aeb1 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -208,6 +208,7 @@ public: if (entry) { entry->state = ENTRY_WRITTEN; entry->peer_identity.irk = irk; + entry->flags.irk_stored; } } From a3bb18d7241a45774b3dc2e55d80bc88af2a93a0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:11:05 +0100 Subject: [PATCH 112/274] BLE: store identity address type in DB. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index f71c95aeb1..0ffaea970d 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -221,6 +221,7 @@ public: if (entry) { entry->state = ENTRY_WRITTEN; entry->peer_identity.identity_address = peer_address; + entry->peer_identity.identity_address_is_public = address_is_public; } } From f905d2a4d446b7312e60f43f3b3908a805e4b08b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:14:53 +0100 Subject: [PATCH 113/274] BLE: Improve DB entry lookup. The DB entry lookup now looks at the identity address and/or connection address to find a DB entry associated to an address. If the entry has not been found in the DB and a new entry is returned then the connection address is not stored for private addresses. --- .../FEATURE_BLE/ble/pal/MemorySecurityDB.h | 52 ++++++++++++++++--- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index 0ffaea970d..b0c6f7088e 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -274,14 +274,46 @@ public: const address_t &peer_address ) { const bool peer_address_public = - (peer_address_type == BLEProtocol::AddressType::PUBLIC); + (peer_address_type == BLEProtocol::AddressType::PUBLIC) || + (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY); for (size_t i = 0; i < MAX_ENTRIES; i++) { - if (_entries[i].state == ENTRY_FREE) { + entry_t& e = _entries[i]; + + if (e.state == ENTRY_FREE) { continue; - } else if (peer_address == _entries[i].peer_identity.identity_address - && _entries[i].flags.peer_address_is_public == peer_address_public) { - return &_entries[i]; + } 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; } } @@ -289,8 +321,14 @@ public: for (size_t i = 0; i < MAX_ENTRIES; i++) { if (_entries[i].state == ENTRY_FREE) { _entries[i] = entry_t(); - _entries[i].flags.peer_address = peer_address; - _entries[i].flags.peer_address_is_public = peer_address_public; + // 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]; } From ae8d5b4de1db4d68cc6e077879bdb9d365795bd0 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:15:28 +0100 Subject: [PATCH 114/274] BLE: Implement identity retrieval in secure DB. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index b0c6f7088e..c6c627b66b 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -17,6 +17,7 @@ #ifndef PAL_MEMORY_SECURITY_DB_H_ #define PAL_MEMORY_SECURITY_DB_H_ +#include "ble/Gap.h" #include "SecurityDB.h" namespace ble { @@ -174,6 +175,19 @@ public: 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); + } + } + + /* set */ virtual void set_entry_peer_ltk( From 77b1903634081e3228ca20d085701db315874ef6 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 14:16:35 +0100 Subject: [PATCH 115/274] BLE: Add bonded device to resolving list at the end of bonding. --- .../ble/generic/GenericSecurityManager.h | 20 +++++----------- .../source/generic/GenericSecurityManager.cpp | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 4ca681adae..e30e4b9114 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -400,21 +400,13 @@ private: ); /** - * Inform the security manager of a new connection. - * - * @param[in] params information about the new connection. + * Callback invoked by the secure DB when an identity entry has been + * retrieved. + * @param identity */ - void connection_callback( - const Gap::ConnectionCallbackParams_t* params - ); - - /** - * Inform the security manager that a connection ended. - * - * @param[in] params handle and reason of the disconnection. - */ - void disconnection_callback( - const Gap::DisconnectionCallbackParams_t* params + void on_security_entry_retrieved( + pal::SecurityDb::entry_handle_t entry, + const pal::SecurityEntryIdentity_t* identity ); private: diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index f73e5caccf..83e86de435 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -864,6 +864,26 @@ void GenericSecurityManager::on_disconnected( _db.sync(); } +void GenericSecurityManager::on_security_entry_retrieved( + pal::SecurityDb::entry_handle_t entry, + const pal::SecurityEntryIdentity_t* identity +) { + if (!identity) { + return; + } + + typedef advertising_peer_address_type_t address_type_t; + + _pal.add_device_to_resolving_list( + identity->identity_address_is_public ? + address_type_t::PUBLIC_ADDRESS : + address_type_t::RANDOM_ADDRESS, + identity->identity_address, + identity->irk + ); +} + + /* Implements ble::pal::SecurityManagerEventHandler */ //////////////////////////////////////////////////////////////////////////// @@ -935,6 +955,10 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t 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 + ); } eventHandler->pairingResult( From ede3d4374335158ef93702ba235f07de88a9c128 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 15:57:30 +0100 Subject: [PATCH 116/274] BLE: Add function to querry the list of identity addresses present in the SecureDB. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 16 ++++++++++++++++ features/FEATURE_BLE/ble/pal/SecurityDb.h | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index c6c627b66b..afb63f418d 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -187,6 +187,22 @@ public: } } + 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 */ diff --git a/features/FEATURE_BLE/ble/pal/SecurityDb.h b/features/FEATURE_BLE/ble/pal/SecurityDb.h index 7c6e77637e..bc790ccfb1 100644 --- a/features/FEATURE_BLE/ble/pal/SecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/SecurityDb.h @@ -107,6 +107,8 @@ public: SecurityEntryCsrkDbCb_t; typedef mbed::Callback SecurityEntryIdentityDbCb_t; + typedef mbed::Callback&, size_t count)> + IdentitylistDbCb_t; typedef mbed::Callback WhitelistDbCb_t; @@ -274,6 +276,20 @@ public: entry_handle_t db_entry ) = 0; + /** + * Asynchronously return the identity list stored in NVM through a callback. + * Function takes ownership of the memory. The identity list and the + * ownership will be returned in the callback. + * + * @param[in] cb callback that will receive the whitelist + * @param[in] identity_list preallocated identity_list that will be filled + * in. + */ + virtual void get_identity_list( + IdentitylistDbCb_t cb, + ArrayView& identity_list + ) = 0; + /** * Update peer signing key. * From 951a6be4c86dca26e7b768726554296245a7b9c2 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 15:58:21 +0100 Subject: [PATCH 117/274] BLE: retrieve and fill resolving list at GenericSecurityManager startup. --- .../ble/generic/GenericSecurityManager.h | 14 +++++++- .../source/generic/GenericSecurityManager.cpp | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index e30e4b9114..68f664f837 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -25,6 +25,7 @@ #include "ble/pal/SigningEventMonitor.h" #include "ble/generic/GenericGap.h" #include "ble/pal/PalSecurityManager.h" +#include "ble/ArrayView.h" namespace ble { namespace generic { @@ -402,13 +403,24 @@ private: /** * Callback invoked by the secure DB when an identity entry has been * retrieved. - * @param identity + * @param entry Handle of the entry. + * @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 ); + /** + * Callback invoked by the secure DB when the identity list has been + * retrieved. + * @param identity + */ + void on_identity_list_retrieved( + ble::ArrayView&, + size_t count + ); + private: struct ControlBlock_t : public pal::SecurityDistributionFlags_t { ControlBlock_t(); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 83e86de435..0b93ac0b7d 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -74,6 +74,22 @@ ble_error_t GenericSecurityManager::init( _signing_monitor.set_signing_event_handler(this); _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]; + + if (identity_list_p) { + ArrayView identity_list( + identity_list_p, + resolving_list_capacity + ); + + _db.get_identity_list( + mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), + identity_list + ); + } + return BLE_ERROR_NONE; } @@ -883,6 +899,26 @@ void GenericSecurityManager::on_security_entry_retrieved( ); } +void GenericSecurityManager::on_identity_list_retrieved( + ble::ArrayView& identity_list, + size_t count +) { + typedef advertising_peer_address_type_t address_type_t; + + _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 ? + address_type_t::PUBLIC_ADDRESS : + address_type_t::RANDOM_ADDRESS, + identity_list[i]->identity_address, + identity_list[i]->irk + ); + } + + delete [] identity_list.data(); +} + /* Implements ble::pal::SecurityManagerEventHandler */ From f56f57bf155db4d2433541994931a21c4d9db2ea Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 17 Apr 2018 16:25:35 +0100 Subject: [PATCH 118/274] reorder enum to add new values at the end --- features/FEATURE_BLE/ble/BLEProtocol.h | 38 +++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLEProtocol.h b/features/FEATURE_BLE/ble/BLEProtocol.h index 79e3357bec..63a61bc1eb 100644 --- a/features/FEATURE_BLE/ble/BLEProtocol.h +++ b/features/FEATURE_BLE/ble/BLEProtocol.h @@ -59,24 +59,6 @@ namespace BLEProtocol { */ PUBLIC = 0, - /** - * Random address. - * - * Use Gap::getRandomAddressType to retrieve the type of the random - * address. - */ - RANDOM, - - /** - * A Public address used as a device identity address. - */ - PUBLIC_IDENTITY, - - /** - * A Random static address used as a device identity address. - */ - RANDOM_STATIC_IDENTITY, - /** * Random static device address. * @@ -105,7 +87,25 @@ namespace BLEProtocol { * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the * type of the random address. */ - RANDOM_PRIVATE_NON_RESOLVABLE + RANDOM_PRIVATE_NON_RESOLVABLE, + + /** + * Random address. + * + * Use Gap::getRandomAddressType to retrieve the type of the random + * address. + */ + RANDOM, + + /** + * A Public address used as a device identity address. + */ + PUBLIC_IDENTITY, + + /** + * A Random static address used as a device identity address. + */ + RANDOM_STATIC_IDENTITY }; }; From 169e579de7b5d7e1e2cdcbeb0e93c1f5048d8100 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 17 Apr 2018 17:05:41 +0100 Subject: [PATCH 119/274] BLE: Handle new addresses type in GenericGap. --- .../FEATURE_BLE/source/generic/GenericGap.cpp | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 877564bb23..19f6667381 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -314,7 +314,9 @@ static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist) for (size_t i = 0; i < whitelist.size; ++i) { const BLEProtocol::Address_t& address = whitelist.addresses[i]; - if (address.type > BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (address.type != BLEProtocol::AddressType::PUBLIC && + address.type != BLEProtocol::AddressType::RANDOM + ) { return false; } @@ -354,8 +356,8 @@ static pal::whitelist_address_type_t to_device_address_type( BLEProtocol::AddressType_t address_type ) { return (address_type == BLEProtocol::AddressType::PUBLIC) ? - pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : - pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; + pal::whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : + pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; } /* @@ -411,6 +413,7 @@ ble_error_t GenericGap::setAddress( _address_type = type; return BLE_ERROR_NONE; + case BLEProtocol::AddressType::RANDOM: case BLEProtocol::AddressType::RANDOM_STATIC: { if (is_random_static_address(address) == false) { return BLE_ERROR_INVALID_PARAM; @@ -423,22 +426,13 @@ ble_error_t GenericGap::setAddress( return err; } - _address_type = type; + _address_type = BLEProtocol::AddressType::RANDOM; _address = ble::address_t(address); return BLE_ERROR_NONE; } - case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: - // TODO: Fix with the privacy/security rework - return BLE_ERROR_NOT_IMPLEMENTED; - - case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: - // TODO: add process to set the random private non resolvable - // address (privacy/security work) - return BLE_ERROR_NOT_IMPLEMENTED; - default: - return BLE_ERROR_PARAM_OUT_OF_RANGE; + return BLE_ERROR_INVALID_PARAM; } } @@ -448,10 +442,18 @@ ble_error_t GenericGap::getAddress( ) { *type = _address_type; ble::address_t address_value; - if (_address_type == BLEProtocol::AddressType::PUBLIC) { - address_value = _pal_gap.get_device_address(); - } else { - address_value = _pal_gap.get_random_address(); + + switch (_address_type) { + case BLEProtocol::AddressType::PUBLIC: + address_value = _pal_gap.get_device_address(); + break; + + case BLEProtocol::AddressType::RANDOM: + address_value = _pal_gap.get_random_address(); + break; + + default: + return BLE_ERROR_INVALID_PARAM; } memcpy(address, address_value.data(), address_value.size()); @@ -528,7 +530,7 @@ ble_error_t GenericGap::connect( _initiator_policy_mode, (pal::connection_peer_address_type_t::type) peerAddrType, ble::address_t(peerAddr), - (pal::own_address_type_t::type) _address_type, + get_own_address_type(), connectionParams->minConnectionInterval, connectionParams->maxConnectionInterval, connectionParams->slaveLatency, @@ -1135,14 +1137,9 @@ pal::own_address_type_t GenericGap::get_own_address_type() switch (_address_type) { case BLEProtocol::AddressType::PUBLIC: return pal::own_address_type_t::PUBLIC_ADDRESS; - case BLEProtocol::AddressType::RANDOM_STATIC: - case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: - return pal::own_address_type_t::RANDOM_ADDRESS; - case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: - return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; default: - // not reachable - return pal::own_address_type_t::PUBLIC_ADDRESS; + return pal::own_address_type_t::RANDOM_ADDRESS; + // FIXME: Handle case when privacy is used. } } From d1f3e4fd27c0d6b6b281a1e934349012fbbc9259 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 20 Apr 2018 09:33:54 +0100 Subject: [PATCH 120/274] don't require master sends keys for signing key --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index f73e5caccf..6a3442b71e 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -177,6 +177,8 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con KeyDistribution initiator_distribution = cb->get_initiator_key_distribution(); + bool master_signing = initiator_distribution.get_signing(); + if (_master_sends_keys) { initiator_distribution &= _default_key_distribution; } else { @@ -184,7 +186,7 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con } /* signing has to be offered and enabled on the link */ - if (initiator_distribution.get_signing()) { + if (master_signing) { initiator_distribution.set_signing( cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing() ); From 0b923978405cee28dece81bc0e54a525271a59e7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 20 Apr 2018 10:22:13 +0100 Subject: [PATCH 121/274] BLE: Fix flag IRK stored in Memory security DB. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index afb63f418d..24783f42c9 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -238,7 +238,7 @@ public: if (entry) { entry->state = ENTRY_WRITTEN; entry->peer_identity.irk = irk; - entry->flags.irk_stored; + entry->flags.irk_stored = true; } } From cbb33ea938746c3bcbf00ef760ccb460e971e82e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 20 Apr 2018 10:22:56 +0100 Subject: [PATCH 122/274] BLE: Add comments to GenericSecurityManager::on_identity_list_retrieved. --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index 68f664f837..c242b7cba6 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -414,10 +414,14 @@ private: /** * Callback invoked by the secure DB when the identity list has been * retrieved. - * @param identity + * + * @param identity View to the array passed to the secure DB. It contains + * identity entries retrieved. + * + * @param count Number of identities entries retrieved. */ void on_identity_list_retrieved( - ble::ArrayView&, + ble::ArrayView& identity_list, size_t count ); From 6a90232b6b40459f322dbd1b5ede804e5f49f392 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 20 Apr 2018 11:31:31 +0100 Subject: [PATCH 123/274] BLE: Update cordio stack binaries. The new build contains a fix related to permission verification of characteristic that requires signed write. --- .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 46166 -> 46166 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 94784 -> 94784 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15676 -> 15676 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 446274 -> 446334 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24540 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 52210 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8668 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270776 -> 270828 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a | Bin 48498 -> 48498 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a | Bin 93270 -> 93270 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17880 -> 17880 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a | Bin 451062 -> 451132 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 46254 -> 46254 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 94840 -> 94840 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15716 -> 15716 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 446698 -> 446758 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24540 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 52210 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8668 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270776 -> 270828 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a | Bin 48542 -> 48542 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a | Bin 93298 -> 93298 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17896 -> 17896 bytes .../TOOLCHAIN_IAR/libcordio_stack.a | Bin 451274 -> 451344 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 45796 -> 45796 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 95978 -> 95978 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15508 -> 15508 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 454900 -> 454960 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24248 -> 24248 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 50834 -> 50834 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8652 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270220 -> 270284 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a | Bin 49310 -> 49310 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a | Bin 94644 -> 94644 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17976 -> 17976 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a | Bin 462868 -> 462934 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 45872 -> 45872 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 96014 -> 96014 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15528 -> 15528 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 455228 -> 455288 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24256 -> 24256 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 50778 -> 50778 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8652 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270228 -> 270292 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a | Bin 49310 -> 49310 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a | Bin 94644 -> 94644 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17976 -> 17976 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a | Bin 462944 -> 463010 bytes 48 files changed, 0 insertions(+), 0 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar index e49d6c553df1321f2f81b5ed76ac831103dd5ca8..c21f7fa70b531cd113b163c47413b8903ade27c8 100644 GIT binary patch delta 199 zcmccig6Y}|rVSpf97ZNahL#3~CYu9TLxkYG$pNfln-7UA@t}$@sl0-Vn1a=C88&gj z)PO|9H?Ou96-E`g?^h`Z7ulSUPy@FIV#cqcO(Jl4u&Jloo48R$vL);6>SoM%Y$t`)!xJn6EOyhWKG^Ag(_mTPKFHt1RXXC diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar index 96af76a1f14d991d79d1bc7a3a7f6cca5894e7e5..0eb5535a3a2bf26d1ad24357508b18193076d2f5 100644 GIT binary patch delta 134 zcmX@`g!RA^)(vbt97ZNahL#3~rknYAOtj&=$$UIwn-k27YGEQ~V37}7gw#<*6z&LR bqljz|aA&OJM-_S##%RQeDrA$u$RY#)V~ZiE delta 134 zcmX@`g!RA^)(vbt9EO&b1_tJ4#+&(gOtj&=$$UIwn-k27YEeZ#Y!OmN6;Ze&l#L>? YJ;0r@jvrO%O&FsQC#sN50waqM0C%+^@Bjb+ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar index fd5276440e687e1bcab9c15dabdfee20744cbb1f..819640e3da3fbedae33d19d7aaa5d423a61603ae 100644 GIT binary patch delta 63 ucmdl}wWn%B5F>|?iIJhDfuY&vD8>W<1n-dG1|9^jN^Su^f~TY>#SZ{WZV=i4 delta 63 ucmdl}wWn%B5F>}7rKN#^xtYo4D8>W<1n-dG1|9^jN^Su^f~TY>#SZ{b$`J+t diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar index aeb550373b66752ec2b00dfe111fea259d179cfd..69861e6998fbc21cb25ea6e381e05fccd7906c6d 100644 GIT binary patch delta 4079 zcmb_d4{Q@v82{d%JI2OX?Z(=*AX|%FCkWlG8=VjwizF_f!NeFcN1`kag2oUeAX(su z0fk^h)8GXO+aL&mC~IlL1)_7AK|oLj%HO5hr~xt*AubqjGT*!Q-qz6>EWPA+-+jOL zeZTj;clW;QYH{9cafZG|YNQHKCJ?O$lm^svk}{a1rd4(33Q*JAwu}{^rt!|wog5de zgyB$=h~njd(?RV4!0ADaCoWwJ_(8FG58#YJ&7{}}TG#FZPKEv>fK_%QIb)OIya!}B zrcDLHF~gM}8XQ1UKuty7$E|q-NTzW>268}F`7Ifp9YFpIms^1RAKbkHWJIXRgVb>r z1j;T0H4%6bXe!h#0{Spe(@EZO8|X+l{2fq^6LKFH!clk=*tM2Su6rr5qABQ8(l0lsQ|A+@0yEh zor2QZ8d=z+#mHA8I6j&F=0-HfHb}*e*>JT#_~DH*)S#0#q~VGM-M=(@RZ9u^c;K&l z0|cHw)7A_!J?B-q4_>*utr?BlxrzP|uBB(BSf0B^KfDY14Y7Xqy1L;=7NZkdoF z%!Fdxw*&NY%LK5sJ|329{^^r~m*JD@C!Ut1X1#Nt{{g0c2O?VAv?;EhD9 zDWHYHj*tai4XQ^=@l&IN>yCP`#!aENG>k0L&CvkGni@uKY#F2N4kHg*r=1L=Qt9Ft zfEsPPm%6b%SL^gr5BBD2vBk0n2XZw_8TH7|-@X}FE;NOzgY4kze_X>m^97}a94xH8A6JeQoDoKH z$Qg^Ew9Zy!*ZZ8rGCb8ijhqvuRv(%{Zkk<7@$r6Cq(9O?D$KeRA8)66;~KKsmk?Kc z#(aN&Mz&c8Dc;-;c9O0llPcF(M=a8}UM8ht0)w;ZJ$K2s6Ghx!wjy)amGb!dPM6Vz z=K7R!W4^fo`n$P4MbX)Az4wBtQDOAf-W~La*;|#0xX@RJX^{}Gh!=jG9 zy6ulWbmat7%Wu5*6?f=*^CzSD54oh6`4uRYMu#4lCv7wT2TG;RHg3Myvr1#n@-|3M zOfglf4C~pj0CtKuIzJCGv02`$M delta 3984 zcmb_d3v5(H6umR^-uAPl^hbBM+tQ^q+iz%*es(F*(1@mKB_@)nP~ryz+L+j&LzC=QQATxpBC$n2$=ez(NGI@X7}xsSGES1-Q>Kx z=iIqx?!4KVz1e2(YqNX5Kw9?{ph#eBF`zJ@g;Ny48ZE4@BiDcy-fN3k16mk+7VhLY zWd+QIW)K`@fWtxM7Qo>_3l!E>0=`o;*8z?gv`CuGSMjR(aYTK;^OkM63>t?)py_W57VSV8@g1RPhHbrASM5xE8Bj^zE!dK zt{xa$Bo*I~FFIwGjrUJ346;&QZ}DCGc1NmFX_+`DD@s{CK`R|{0DZ)Vtn6eqI-4Uk z(FW_QMwNCcQC?+X*_+X_B~lZ!v6ptE)s~=C<{9s|V3*7D)bq3C1umu3fWavqxjutG%6YxKBI#8iM6^!!O(9}zJHK=_FKgox?c09Fxg z0EHqZ1scL>0J&lupT{NQVt`FNYO#v|b_yXGphrY*16`&r0VfjWuem^?L-bPi19R>aH7{~OBc#fM`HjI=Y}GMn|L;kPUk94JRL_Hx{(vdEub}diW8;NQ{8-;;|l;B*we5r z3tw1B9X=%QfHKCcDBB#y4QS?Q^?H{cm=Nv|7dtI6}NhlKO9- ziC)rYlag4TjSZhCIr8Fi9sP&=lqsibNx@b|?8;@i5bBrA`O1cP>BH(>ijpWP!4 qT9|KAU0tqMl@}i^G({Il#uC<>&Mc5L@OvcBn|>~p8sq!5xAs1 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a index 050038521c06bf542f4035818815a51331db4628..c550c6953c37e1bc27d0eb0ecec8a2661244d25a 100644 GIT binary patch delta 212 zcmcb!pYhIq#tBmFMkYpv7M3O(6|b^zK-q?y|FPI`zrU+YvJWKCk5FSx6*!IW(N O>${K-ReDd10y6-4oIbz+ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a index faf8486eb4c21553e7c0c4749e9fac347b577732..0a269a1b376630447cf074a90924899c6ace99e4 100644 GIT binary patch delta 132 zcmew~o%z#r<_S_9MkYpv7M3PP8E&ww9&|w1(0J~%=q5uE@ delta 135 zcmew~o%z#r<_S_9hL)BF2IgkQ8 delta 79 zcmccPe8+i$6o;XurGbIDnej#?5k@#?vmN6Ob_DMq#|btB?;QUXPB?G!IeziY2PLIB E0BI8z1ONa4 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 7d9dd41ab43365b95889557c24693e9c7130951f..5a2187d27ba83873006414fecfa8054a1d13bc33 100644 GIT binary patch delta 3988 zcmb`KeM}Q)9LImpb9b}_S`S*dDo~E$Ha0c{LwP z)aW8X7x83|fPd)f5{)B4J3X?fnNgE1;%w(i%t926Z%c^5WoB-fxO-aeXc4wqOY*sI z@B4dsUM}~vbes`;&xkw6n2Jk^i%QE%j^uoWh{Xvg9=KKkiUAT!Q5G?WJi0WtdBF@bHnVK~Te=3|~b18}@?y8*l1gk7SURtfmun0*8Aldxzz z;1MB1f@?1W)*(D#ovrPFhhxV~z)u5-rTEl5z$0<~d%%oKVl>?yfQNxRX7>64KLs2< z3kC%;a12k!NRZ(JvsMBZ50)GNPN&HaoX(-Kz=a_ChdAlk?|^#}$Z*M5oxm|}R>lQh zcn3ye(nx{-@Rgb=4&TPa&+^OzKW2)3w()aD=|63hK(*xCQt_HoH++F=t3$sDMgLy$ zMPiiEzOEuE$`H4{X^JvF-M(f>#-7QB;j8kt*(1`OzAQCOiZCSK+dsZ zfEAozI>alF{^)=Q@Nh-aPgXgj zr;vnm`U0b5M~_uLT#*u(0!iZ=O->RtHD6o|;~ajZ6cW4}njlwb;hQ_ALteIDXid$} z50o@;z_$p^GO#weJ-ZUjLHq0PE`f2pzmV`PmYk01w{MSz7olb`%kb7^m{8EWIBO%T zPYPIM=5nqCzx^5fQBgzcWIp6r+WSs&NbXebU6Fj^qj?#PAIdNY^D=E5&v#Gcq@d-%Vu@Xf4-^1xj$8AyBxq+u!d|YPHIW53~qIO9I zGyD?T+VDlxc?v{kUi zg_`0lfMk}C%~lpJ7|T?Pmok+BW-`?#IESgWfKLYWI8&|e1k;>>32XiP2mEB#Uz<1- ze7tVCdS5_qAZ69&vBC@!fQQZx;9SN3gFqWiC|B5~d2?vh7Hp@TCM43DZ?HhGu}F^= zsiFH>B-4yUw2W3w!4j=xpL>&D_zJ{9_4&J7kzHL*6P#+s4XQbp1c|zPmgkX8c^}z z*}=LN?n4z5B66H+V-PL3L^zU~c@zO zgkMgL=p?B>uf;ZF6|`svcB+Wr9SM3;*lOE~*Be=?mSri@6V$1v@FL?(3#Xquk6$p- zX^vZKYQ2Q(joqL*{o2}(b>lyc1D#ot+S!Y{jOQEfbsBT!`TAht!mI*row166ULLM_ zaIK+U%Vu%u#_=5PwSNg`eJQ%vg(hx-aYTnFAs^y4WawWz6O|Pel6vwiS7!WMtvl#VdTw&RWg8YPkg=pz3H%3{{{W($wQ~Rf delta 3932 zcmb`KZA=tb6o${ecR!WISyX;1Gs8?^@G^JyGS`q{o>5qspI6=C9p?`YwE-eAjEgs z5;lMk$32UC^VM4cjX;Pp%6)+1p|S^1e9-&P8uzsQe_8-g!VnS}HcD1k8K7A74gwO` z$KAEjJU9SoB#$crF@`O1fs@N17D6oZ8PDqgoM?(HfQu{w`-o;C2l(H3qYd!$ux=&b zQ4vNgetraSnC+c_!|dD&I2QFh;1@xNr}=^p@Mv873NYh(Pc%JsfMXy$V-6k$`~nc% z02+CNKp6hI(GX%UtSADK2-a@`5~k@ekT9(wASy!mOM>)D0Lb$o#47IX2g10+B?N=f z3!_mm+QNVMV%dC$Ts!6qU-*w1F}TVp=guk_7iH9yEaJn499(5{gb&0^L%clnVbhoh zBVBIa;vcISERfr|)T|k-Wm{mgUU6wCT~0YLPc!7@-<(X<%7d$TIa3+$3>(tvyT~ao z`|;i6Xy-=H60PZP5|#V6b4-F9=<4O{;4l9b?l z7(1)c?CCNe{HX$_XV9K3-~=S%{m=wC#^$q&LGVrNG#*NsIx}cElnt4Cj0Xw$)X2%V zj+gXaw|RfNx6fqlax8gsJxn*!2&=m3*~NYL(qRg0s$c`jH7+yik}EQ6Syoce>SZqR zm^)Lm@h666gV(+XWi!v(7CMi-SMOb1#LhQ#M*OQcS$02JLr}l?u-PTGS&2hx#b_-W zkZc4MNIiXslfGMmIkC2ple`(m$YC5PL;SC?3Ub*2xsr0 z*>nv!wZH<`#E;8U#f#s%#ZaS3nqol3(q{&AMsU-bF?N7yOj7`AnWh4qVCn$)p6Pgi zZl-Af{Zz3Nz{8Gd-%O^oZ!ObwfNG{004+>ue=AcLKs!^KGr*MQv$^Q{2jF2}XmCDN zOs7d=1vH&zstvhJ>H0jT698UkN&{9hr2|ww)efe#?;KMvz-^{r$22k5-kqtKpuqgD{?!Mw6@7!`85&q?O`bdX~EF`E@uiB{GXwtX0^ior^@Xcx8@&>rIhW z>B{Y$c)KKiZ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a index bb26c368af2aea1a2fb0a952024c8105edffeef1..6a01fae91ab30e2b2902da546449cde8d6c87dcb 100644 GIT binary patch delta 202 zcmezLi|NxZrU_E)MkYpv7M7+P6|b_u*pmbM#5aqu_6Z;fNNheRI+GVkKyq`HvJ|p_ z#OBQgt~^L8#5arCo)bn9U<$N>3rtiL-yD;|g~D$sKPCp#0Fuw>^&- zSz_~M16Lj-0rAaZw&#RV1egMCPz7RAxKIUJ%8!X5X_4HV)yD<5Wul_^=1H?z;EtZC LD6x6#*1hZi_3JpV diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a index 826898467015307e15d4bc7e3bc6dd78ea138938..4ea76bd287b4169e65a7e87e611b058d044baa57 100644 GIT binary patch delta 152 zcmcb1gZ0`C)(KJ^MkYpv7M7;wlNBzAZ?tshh6$Je1;jSb#j+o??qKX8p vI-$xAHD;os#Afpg@;NXSAY;Y0m)J0_5JVP|*ly#;$OX3xqADel@skh$-!?5} delta 145 zcmcb1gZ0`C)(KMVhL)BF2Il6IKvBqF{&C6e)z5CFlwE6M-> diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a index 044939a91d33b1520cbe9611ddeb08e54401a76d..97bb57537d43bee84679a44f9c29aa6d7364e9d0 100644 GIT binary patch delta 88 zcmcc7&3L1mae@?wk%^I^g{7&*j+KZLs7r^p290( LxX9)UCLDqQq2(F^ delta 92 zcmcc7&3L1mae@?wp{1pPfw{T)4;~`yvdONl$ga?aO32Fv(LsD-MuSIi<9f_%;8k*>Jg!78EL6m6Eic_=I)qpvbGTA7LX%BKyNRQK%fMY6vP}Qpss`0 zfD+i)g4Tc%;P)0l12lFw{0B;ZF^K{V1bK}>1BBvAEd3kk|3%$KpuvL@%wqm)UAY6) zAMQ2)y{j~U5NYs*y%B_gaP9_y<0&~XEbRfo9~6J$K&|os2*E~k1PBO)UwqKs4Z?$P z;UEYPgT6T+3=YM|DUPDx#drsZI;J#$=nn#Vy3QZUdq8zddQmqGGCmearkMZXCSXXk_bP*D6N zte6Kf$J)1ogB_Pa9t_UG91qsjDcO}Re}#YggwG3&+LX4yBTSgc-*8$I(&vxzRkjvH zCxy7*f}E_RQ8c%7tgA}!Rn}}j7vrlG?JFDRspCxLm3N(NGs8YBMiQG{_owl6EoVHr?9iojmo#l2xo-6?+uBRaTK*c+7w;<-)sdsaeI&t|lA)el zH&#=cNi88?v6NC`bshzPZi*MzM}|)1{`M)ffA8o24ecvbJ+4?nqJeRPZP-O#N}WXT z-t&n@o;koS9AGbGISE1>S<8}JNZi!g0p9w4wh^m+-p}UM_YJTQvdLv6jvarIL?rY0 zYv}(IyWWQP(I5lG`>#>UKycfP_J`=R5VfmvE=$@?&a?b=QYgz=Kti;zJ!EG{;FLpg^4L~?cj#Bd%4Fq|_Q80xyjagGHT&DjR*_^T1Gn}!bJkALK1)K$dIh?WR^PDXJ^ErOsrvxW=-Smxn!@+h(p?dd(+02 zNV17lC*z9SO#q>4YC$|{VxJr#WAx`yjoqwWIzrAm?h6*}mtOK^@_oUq)yLA5$o@jl zI9g@XABIlX!>~4wCM9~Mx=4H&o-d`Zd!M4NKd{>BIy%2lkIK|Kuh4Cec}-WH&3Eau z24Cs+P@&w^UovZ|UAX2=%yK2xJB5r$J<2UzpCKI8PZMXBc3`Q{5vNDEjvKA1QbAQZ=W=8@?-leC;Zp?ZMS6D!I_-zdX)ak0Ty z+B`+Pr5{Y0u9He@C=d_N^E8#|K7Fbh#Z@DHCBq@H)|<$q%v$RiF;$<6C(&?KY>U+s z-N)ATP-)p%UujLcBM$p@IODosPvomzb{e$YJ^ E0{qacZ~y=R delta 4316 zcmb`K4Qx|Y6vxkf_q}ew7%dxZ*%)gnYzTGhKG@nZVJavj1lSY=>I5BNM(~M? z5ln(;puDQ)t9zuy17 z=e*PNUf*r&8F4-5~+~{MKMN=sOsny zphniVs1=|_c-KuRft|48j=j;{wP63ti+QiM_if#v%_`oHo`0x5b@qnWJlTsP}L z>Pz<*gLGeA41Dl+;j%9W-dlNPz)4e%My3_}fcGV}FSEB-SphuSI?xClrP3ixCq4!K zAho;={9)7)54?Y=VUu!7J%p6e3bL-ri$U&7#pNJBlGF$iRL=vsKQ&;{q)S!dx`kd} zQhS+7>`{0mveXtijQGTDtZJw8j=rgDq+^jy}Ktb5s1 zoHqLn*5S|t#oipnqP^;4O~b=1Wr8O^+veR{oX$Sd)Ec&fv7N$I&XV(*0N}KQhrr7K z=a4@?K zMok8Y!!%$67)*=-h$oH#FcXIX3@75c5kx$s67evKXbUU_umhygcmO~;aWp_C5#zIo zm}~;k3g9Lt0Zc@wlz0*unD|K|CZ0mH0X$2@#M6ja)pVi*U?!0R6ch0T&l4>GFA%ZX z1w_oZh&U2pDG~FoAld-NB0BNKLGpfHW*4rlERMl@+ND!VBXh1AF)m5ff}CVh?u^@q~3jzmbS1raM|n>AI7pQ2^J;$5z}T z;`)DxxGoXfNCo5)alVjv=pkK73W) zRNgdFx3=3Y+K5tKm)dPuwf0K>xKlU8F*~7UpgXu=;Yd`)V& z^slYlQMmrOJ-9Os*RCv4mYai} z@QBXA%&IL~rwIL0d$PL%6NEB-yq+xRZ8)xM3?=K@t;}soh9#5@H!!QV!eHpk(IbPm q+@=D<&-%XX$<dpV}#(m$pNfln@@>r@t}$bseFQqSb)_i8Fq2O z)PO|9H=nka6^4s!{@^!55W$;}&;qvuqTi@^mk3-QY$8`j7dNWNrpddcP(`}dsjvY6 D{NOZw delta 195 zcmZ4Yl4;#brVSpf9EO&b1_tJ4#+w6JV}#(m$pNfln@@>r@t}$bseD2cQ8Mh}LRKTb w`LwmHFkEEw2frDD2;PK*7BoAIig$^?<-xXcb#!r~ifo#^OA1w_Yn=)k03mTS*Z=?k diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar index 9f64cd94d869229c8bf745ff3e276aca4507c217..ece6adf1fc5d801235c9b27e6d2988101e45182f 100644 GIT binary patch delta 130 zcmezIg!RW0)(vbt97ZNahL#3~7MuBaY_#FL$$UIwn={O-YGERlAdyX5rPSd9)BlAr lif^{OBbf~s0;$Q j+47ELHe3j#YkPq^V;etQXgg3<04JOaR*{py$Rh**R^1}Q diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar index 57856773753444e67d5f820b968aa2bd5850d029..a44c14e6593423372ea447f5789fba8a7c69a127 100644 GIT binary patch delta 71 zcmaD-^`vS;5F>|?iIJhDfuZH(J~^??1&l!g$RgsK9||tzfs1VJlUu=$;MwV^@dE%C C5fniH delta 71 zcmaD-^`vS;5F>}7rKN#^xtYo2J~^??1&l!g$RgsK9||tzfs1VJlUu=$;MwV^@dE%G Ci4F7=F*kEy#y91=~U^pk;_m1xty1Yy^i{GQ-H0_=6ax#(-O3F~lGH(r}$& z%q3(dvh9S8jLI^XZ5gZFWY-Ww=6*0kjHynYlflR~&8$wD*_gp7JLk4N(5@`3w#n0{ z@AIDbIqx~Q=iIwzR11Gj*1sNyRErv`xh7slQL@_%se8jyvdMkJ}@ z3P=mdnU5w{ zhqVpDRkzfkEe&vhmwxIMK2tGf}T?*m$_>6l^>xBll3M5 zY|410LwSRCk~i_&XmiG1yqmRsibmBR5Ko3a6#kgKG%p4~@EwmmQbQ1#$3{M1=5bV> z7$1S z@-I*iV!rLDfz>!nFSEnhC|U3M5+THTe5e^su~{E-;SO@dXJwVgky$xJ0GhfFKjlI< zyO-TqjW;jpHs2_~y@IUliWu_e5`a8*`#5qbnP~uR?5B;?g*sT(AX=^b$dwvaTuxos zna=!cXaQcE&i0pcek`5k7108vE*+qcs$$JsMgn4^!}L z_G&1tNNT!o962}2&^W4rOnfa>N{kV)Z zc^C1pk!+pU3}32EuWcueP{?vabR za-89I)qAN@vNm>$FW&JbNCujZiS9;Ihx z??EYNoVKqBdwGHn{p1Yo3cozu9-TkF-{gP5qw_odguLH9Uo|TYa@Rci&Q7In?VKGC z?fRKPrB}XZJUYL)UyyfpnLhcK(j@;0#e8W;~o7 PEvDbgqO?}8NiF#YFpNv# delta 4011 zcmb_de@v8R9REJg^S*~3AlHH3;bDMBfTDP*aCc}wNV8(fYGbW2T>hapu@-avQKNXN z1(9=&b&aR#hDSM9HWhfCkE51pO&P0&#TrYbvu2xGfLod)iJs@)dmlJD8l89B=f3av z^L@Ub=li_x`~AL$KX6^^aCM$XS}hBqcCMi>vCy6`;j;+Y(lQ7Uy$| zqX3-I1OI|Hoy_?ha6H(60mlg~oLKuK;JIR-6>#F9B~mQ5*43SWV_~8g@Pt+jBzbQ% zvfcnP6RUcF2&_99A8L4BENHRFnOuV%NTPA98wiIc{-SVZ50L-D#cCk`2Y(#_GCQ=W zpyFx=iRH&YG2vegN-R`t0_Cot#UarCGbpp6=PW1!eK;CJBcQ~BHj^CR3(8$Ub(exf zWj?3^+kc%ETFhYcCQuWB?){*e7=9X56F1L+YCtnD5@szcSHs+)&9b@3NF~UfC(|iB~UvYn}=?oO z5nmK-$M;}pi4dYnJ0|pnPtYyR1(45u>k@!6VY$CKVylH+1n_(${&j@^PS^|pp(ElW z!e;S5u5Wb$IEBpwSRt(4C#}XS+}Veu>bWUL_w52GXt7%=S3Xi7HRv#AuI@--OZK*UQ z+#LFljtVTNQvq@?4Z4)2_@^}5sv|iWyo@(s-g2{pyrLf+j0_{yD>-Ici0>pzm+}sF zu%cXi-_j{A+{Seq@G05GUdDU2P`0a=ZQF;dw#p3Ny-qf86@Qd&Qa;M}aj*ju_<;qI zV|>Dl*`yn8a5kDnGN;m*%|rf><@t>A-0R6@Ic0pt_{iHz*2{W)v^8jPvc?9|=$Rp( zeVlaIB^RDX!)HierleTsMe_KR`pG-ww`>_SPLZ6Y+?YCr!MTc*9g_1KM>*(MZp!2N zDZfV!rdKGhRhfGJ@cxwtm9ugh`VF~NpDMX>?ndNZ>{Gsxr5mZ$mz0JjQjLYil|%CB z`;GB?$gTFvS3qPrSfEnvFh{u8W8A;09qPm8{o@?}fH>KSW_9g~h`QIqICr8b$@uDc z1Ec&Ae>to^We#Yb6n?$d+)}rgua_wlTxq#oJS7yYu?(e3*GM~1Yx%uIa*RK}HqSq| CkosW& diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a index 8befd91f7b7268c72dead5d56984f890b9ab95ca..3671aea768275c0a22b42b31cc8a567f80eb39e0 100644 GIT binary patch delta 212 zcmcb!pYhIq#tBmFMkYpv7M3O(6|b^zK-q?y|FPI`zrU+YvJWKCk5FSx6*!IW(N O>${K-ReDd10y6-4oIbz+ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a index 95cda1314c12734e847d2aa200d656334c2ed9ce..949c4f0a4a6d9b4b8aae732459be8a377bfb7adf 100644 GIT binary patch delta 135 zcmew~o%z#r<_S_9MkYpv7M3PP8 delta 79 zcmccPe8+i$6o;XurGbIDnej#?5k@#?vmN6Ob_DMq#|btB?;QUXPB?G!IeziY2PLIB E0BI8z1ONa4 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 673172faae5bc7e11bbb7d30772a8b61e43b90f6..7663528d5488333b9b1e81cd635bb627057e4826 100644 GIT binary patch delta 3994 zcmb_fZA=tL7=CAVm%HQRT)2Z<1&*cImX;O)Q9+O9q*#qLZP6yR>JNs=LN8lq_YYC;G$HMLE}?r`kN;?dUgE_wF3 zectDN=bhQi++N#hvHP^RW0a+!upqyvxbSf1H;C9IK+%AEC7=jEB1wv34vDDi=ruqh zTehe*Kq7c%5f47M70?h6ldxbOph&Pv1QZ#x=g$&rZvB6>6atDGNHmKLQ>$Yapm4Y@ z10w8lr@@S#c0fb%a6cf1K2Joz_FWJTB%Jt^CQkz#ZFoF@Js!d?W=tsq{BM|b3-GgG z(RRSYf(!|+xe8bZ;Q{N|(h4{nYG(j`9*{_qPtF589M1m;nBkIWMrRw~Fd$Ef-2uSQ z0S=!51GzGA4BockK*9%Rt^h6?SiBE79rXd=bQ~BBTtA5ZB}#ne2jHFsB%JxW1RTTd zvZ#O;-iP5ZVYtA5=t{*Tr+-82m)X{Vmze^;eeCQJ`m2o+oa6FuE`3YV1%Gf(f>Xcg zkN&-UcdSWhU0WJw62vX7MK`D|yT}^fk5?ucGe)`C65-xX6 zADrUydwSO=40iAZMdOQhev(Z(t-wA)VLxTV2(Ux%Q5QI>wzcl85|rwyB-|`DABlkk zkic?)S04Y-_n3Fj51g*%oAQX5$?hRLJLsz>Iku}`S92wYj`+4ET4Fm6md5>@Ag6Za zk&vf1I6`)ICCCR$6N8f=Zfu=JA{~~-i9lpx+4JdxAr9yK?`U%P&5j$Dv+2-^PuhdoWsvey4~-6X?Pv z$VvCy=i-&)4@9(rqKi0#it7*`gR~VZM6~ZioT9Yd6_p+9dAixprRAU10xT$Mmn5*l zFa1j!x`-O}47vYHxlxx)?K~<`Ub^C-@ABv{0k>v~O$5kgoCGkFu>+uiu@m5X#>oHy z#wh?d8M^>_HO3Mc`2|eZ@)t551yIE}6`+N&mcO5I8o&|8TAh20og~yfGq|-`u)=v7 z<8**{X2@VO3nh$Zti_8M%K$SNYYon3tWDta0Y1i9%RA0EbD&|Ze&2u|&+2Q9L+)p5 zm#Gf~^fppfZW=92vjBMM{2_jXjV49;hpIXfo1rjI+I2L?7)N2A`a3AuYIvA(t_PhkXYG54Rttuw+$X8UeW+N} z6{_|7rh43tmzbL_lkt^Q-PAu=u?PS9WH8o{cM9HQEEg*@QoT6~Zyj7nQnxL_uO}IW zSlZ<^*lx^&=GS6LMFiKz=%$c#XbWCvxKzz$%hwI+4$3WiT>el7WRpB}Rt#zR=gc(W#U+`Sknx zz2}^J?tOhXZT|(~)CFO8rgdsTL4N-1Stqg&BgxhaC>i*IfD%ATBq@nGQbJuPuK_8s zZA)4MQUdoZ;mKES1~drCV3Y*_B|=3Ppu}MJpC|5W{r@xrprj!sv)B-|I!gh?qq`rF z#NTeOHgbO-pus$<0K^%vB?L|_g?LEu%x65m3vjY2v;i)(N&L;od;##k@mee3=V8rq zz(XPp8vNuC;0Rkg07uxq8E`!6M8GeClt}W~0N|mxycaO%N|%wY8o+Uoo-z9m0)7Dq z-VHjF`hjqQHA5lAA6QlhBpIyT03<@gK_C%Y!ay{n$VHO$Vl9y8L5dgL-3x?sOGpYP zvmb_H_D}==;mf6SU265P&jOJjGjeE!Tg{tZJi=hq6fY1Xh8kMoa78}I=O2se!Be)>Zj45pf9z4y_RY}^<-~2|R?EL?OpoMfj?%o0OjH-q zyBP*sUHao&sYd5&*J5L;S{UByh>a1+oT;<+ydRKSY`|aU8JYxO1f)XvWP0V!R{qHo&Nola}^RY(5O z;g%-b|EV0NWU`!W5F{kyMreRsbJMAXAO*&Bm=B~)m=-b}$bnJ2%=-xh zw36d)94+p?;_&}=XOG3+>012yT9{&HCG6Uyrxy0y@xXZ4P|h1ttFo-9Q!O7=&1H7sf9cM-1$@2Xlk#8PsjBzMDuR0D2TfT@tDU%% z7K~P-KE*-MY^AFQ3Cg#Nu^?C13yOaoHYq9FaEg5TBb$8&0!RZ3>`>;d!|94pg}sXR zArYMItTr11K?|_KW%+}$bot!ZUO8NEQO284k@B$#os_&RW|$LTGS@VKYOd)3$GExx zzT-L);2PHqfL^B94dCOSS>80REN?Ye4?rc?On_#tEWd?o7C;+UR;Q0EtIzvl?JCYKv> z{SRX;E)(k>E61^fQ=osn5?`u%N`VT+A&)4%VdvxY>G{_+TIH0x2JE-cdZ1E@fVT0xSjd{KtR(Qqn$ zC%Ob}j!k}iElUs8taXL>?x1Na=HqSAvm_KG9-2{tcSLJx)1Fy_C#A*K5~+O?b{JMA z(wP#jv&2Su=*{hT^Ps3Lb@)MkY?PbUp2bV_!-}$2=NWR??f4mgu5S)yEjgo`F!efd zx8K9pqPLzoBK;kcq6zvmJcurxOe&+R(5${7X^O5@v)GxN;f_rdY3Ewvm>6rh+Z)NO r=z*){l^h{kqx-E{;fv%Y{ZBJx)|lw_XaN~xq9%2Uo|1UX5 delta 208 zcmbRDn`z!}rU_CUhL)BF2Il5QlLc(WHd^dsfe9E)3KZWg$~sX1CSV9svH6JTJYH0h z24w{_k$nbUJa9Fe1#Djk!+Dzm!w{TFffAd`Qh4A3AUB9_URZuo45l9Js?8mJ0&p9Q RHZPbhhwAFhceWm42LQOHI4uAG diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a index 43349bd81ee4392d0346f267fd866c4a5bd7dd69..18d077db45e1447cdb1b155826804fbe637b96c2 100644 GIT binary patch delta 151 zcmex#gZ0x5)(KJ^MkYpv7M7;w)AMW?#Wq@aaI-^2CMt?=p2y9jiOfG?QdA1lVFuQ* tIbzirRhSUOkj+jPRC3@#+kxgD5`=TXnzsA-F$!>_h>35njb!{P1OVtRDk=Z~ delta 152 zcmex#gZ0x5)(KMVhL)BF2Il6IH=2lVwD92Ofbxx}=h-ldZJx)?qX`o-fe4*2DJn%1 nidc0<71^N8P8U>ikOj84*f6dUL=o}xV-(;<5vhq}{3ZkdpQR76D|Is@HdAr?h`;2F%X);2N&6VL4idC&I6gS J`IE^v0RSo(95es` delta 92 zcmaFS&G@35ae@?wp{1pPfw{TaR76D|Is@HdAr?h`;2F%X);2N&6VL4idC&I6gS J`IE^v0RSqb95es` diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a index 8fd30c85849da6da620400ddc7251ee68d34dbde..59ac1273caffdaac5165428e54484e35d2281062 100644 GIT binary patch delta 4440 zcmb`Ldu&rx9LIm>+y~o$u6xjS@0QKFjfIukQD6o)B9q`CY*9evCC`N*0)c_zyi5_r z;DlY+NfeO~A%Z|E6K)_1@+O2J#2E}A+aH)P9u5czCc^M{ZhPCcZYrfqzW3AfJ?Hm3 zzn=Rzw>y12W9^BIwdrwgk9*LNpEQ#Q3LXU0ym0l810hmg8wgw@=SQcR6G7-kN_XZzyp=8xVlCea5PT~XehAkwtn}a1 zS_Z=7sIvux9);(>Yp0mK3W6%$4Wgkk7l_@ddNhbnA|;yO?QRfz((!{Ja$Q&yt{W#n z>_$qYDaG%ACz8hnlA&qiLE@^t+>?~H23EH;7_ zq%2=4eITw9KBNt#JY_LmtsOc{?1VU2+Yw^rtMxs`CSdScPAuvQC$7>!3{Swx$~du@ ziOAl)0pF&*Q{Z zeNVu(PO!7vN699-fHFsm*kAq>JDpTDRraTQC3W*}PP(->D=(nw>e{`1qyzZfT$+`n_q>tB7W5S?jbqKUE{XlIo;X?jDB6dmJ)oIVE8cOV*`4(ymlh+E zjPO!B$j*Tg-jyusF&WP{Rz6a&YOW%>#vX26tfa2|a4UZaT^4+x`hVDJ2b<`WYGVSg z{`l5P+vz8%K~KZyca1rislHgWX%kFBT}oHWs@-)6cT>YH>J^5B3dKOHHgTkICbY@u z)`*$Hft+9<--)#Jm4Z98@#xlEpKu^Fqi&5jCY(+W1bX>~Wzz<<3QLS!0qanwpymX= zjMv5ZW~4357UPZG$nV*-&x*zA=7@0_W#V7Kae*DkQ!SnzZ;T6gncKzrnITV~WBYM& zLsGChzP)LaFNh_^5_y@vdHHULC$fU0bZdRQR8tskrF*0}V?6?aWz(b@WB2s3q$Sj* zovf8UH!cG2I)_cGXVRDfMka3DIwI8<8FiNMlWo%)IwY4hmIOkPj~e zL@+Wosym<|0ve;ZXkoG&3>r2zM!?{ZDI}0VB0pp^EQB8z1?GF&-fpd%O6ij4JbRz_ z{+an(@9@JG?WM-8-T`w`GgXYLw`9)A;@wQ1fgjE#EFZ~f&3s) zh6`SC31p77Vtmk44e|&m9Lez?x^HIjmgfGXeOZa2Z!~UJ?I$MRmwC(NpweJBH)pt( zTSH%Y3YjBaFg5QlHD*UD-5cM_7^;|?m4jD}VP#c2W^FjOZhWMY`eTzJQt7$Y7M1n= zou$T5dqqywt|J+au*uLgsuek;H&fGc*|k2=q`tP8+_r>D7crZTnA8oc3C+;L@&XU4 z?rS7xCk)ZNl8Jf>eVY$XBYV_lKiN&l9#&pMEcvGa;0KCB;7^7w1HiQ$TCvMN}C0nV<8Dt2n^$JERV9QSVOa5nZjLLqFlR%*aq}B`UZZrv7^ru zJzKGc=!<`e^7o+qGxoF}W5#h`tZdCla=*mMmebzaf`d)|*79zIv2= znvlA*t8abPytW;Bhg})CbAN!qGw0QU@5m7*BESqJ z=4vGdFBY4_MLWO~oUvF5XYAxj&XWNaauxteIb+dhIhz2MaK;Xoa>nLf;A{o(a>lwZ zb7l?G^;@O4#cjenw2sV9siBH`ua(#du`}yQV&ZFZ9J7+_0OvSk zI}}kJQ^1~o7=cH zn>b_sc4Q?97iTvYaKe_5;}mC{n7_DmQt*YP=>XTcj?df68RPGA#<)~mE8c*cGx{Ir zjO$dw8BrF}pW}?{xRNtA4urB9?PM=Ya|wxLJaeW|3!CK8kwVmWRY#` zyj94OKEg$)VT)Fh$uv2ct!fpFz7zBHB!#u|pa7YC`UQF^B^jX7=h&UX{5C;PYm-^) zQ`G45F3^)s_R=YmC11pdM8a}iayq@L54&lOfq6fZGs#RwI!P97Ffczi53o{h_8HhB zi)du^okUOnGOzVON2=I_(`1@Uw&QvYJ&8wT#*WaME;S(=EIHSnu@-i(h zpH<_rrEb1Kccu<%`>l8iK6;;)>Z7!MI$>kVpccsWqzkvgxdp*FN(zOdaJL1)Q}yGy z!da`98;CQhJ1T`^wm~iM^c7nLr*=UUH8@PF-!FWdqCG1YwzmsswBONzi0Z4t8r#qa zaX@%KECj9{wZ$qXY4=4@Q0mDMEA?7hQ1Z?a?+!-sn@3$&CZ1UwjtWQ>Ux+KyBBh%h zVxuASBpzpQRX@2X=4&hCajJN?T$wZ&f)8s_FOQN|OxLvB;PzLzB{@5+skq2*X_uHM zm*LKvRb8$0p?xp}OI1FinR&q~?vv7{a233<_%>hYmvT*maa~QaS`ftr$T@TI%@YemMd2cw*R`JDM)2w; S3P{6wlh=ugZCc9i%O`ftr$T@TI%@YemMd2cw*R`JDM)2w; S3P{6wlh=ugZClU diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_hci.ar index b4c2a8f94599403041f09ca58604805466d60c73..37280a41c55571ccf6843f05763b5778c6492341 100644 GIT binary patch delta 126 zcmaF$mi5(J)(sc9IgCt<3@r@|O(!p~5ZnBYdzB7cWb*0Hl^D`Tzg` delta 126 zcmaF$mi5(J)(sc9ISef=4Ghf9j3+O!5ZnBYdzB7cWb*0Js|{NB{r; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar index ced1d82ea3903f2a139ce6c637cd0244d2a5e9ee..f49279aa10687d172740ace5d0e057a5d739bd5b 100644 GIT binary patch delta 75 zcmbPIIi+%g86$_0iIJhDfuY%EJH`WiaNcA)M)A$E0#|vEMZ`7>$TA5ai->PF)J^6G E0O<%4HUIzs delta 75 zcmbPIIi+%g86$_GrKN#^xtYmkJH`WiaNcA)M)A$E0#|vEMZ`7>$TA5ai->PF)J^6G E0PpY;VgLXD diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 8072742428eb918b402354b6eff3a7ed53b9c0b0..5b653cb615087896593e836c9089493af30cc397 100644 GIT binary patch delta 4037 zcmb`Ie@s(X6vxlG_q``}7D|h@fC{WCsGzhsbjuWC2!RC2W|qvDEM!YGnnVOg9e{^Np+1jjQ1B1;yD^9N40WgCBh%N9nIpmPq5f!+If@3oH=Gi#fC zdwM?So^Q{6y|3^7Q1+Qy*=H^x+Yi{41P$*6Ohhb^rX=>Tgr-j304%Y~mb3v_g1=h= z1CX4v@E@^Qxcmx`L{vKtBtbEwaZeMF|EuO)AjuO;rdfQihbchfh`Iwn-Aue?H#t?L z0G+P#Pk>6*oJ>sh_kqR}iwCE(BmF>=t)4|dg_wMEsQ(q9PtvHk0#6|&?Fu|W%voGH z2#Te$a!@SQdO(S%x++kfNh|?__F+(F(oNwfbxZ6zRu2N8#1oqa)r`IHOj>&zR7=~& zK$T+sGm6D6o)`c%8M>~3YUz;}!j$IS2Bw(xAvv*n4QNj#7N?=%Bxq6x&m~9Q6`;+e z(wPcR=50G%pB2msuL_4=EDrI|Q4F*#F8MRdCU15LQdE1jFqZh+0*&6qPEvLJ{drC@ z-2Q2XlYIW&I**f#|61yIlA6D^&UFyIF9oymVo|2QJqn@>FH`ms~^BPl5B`>nBnt*`XtP5v`6Nn!Pk zO#?3f%O1;#9I5fL=_$&t^3AH;guA~)eB2p7y;4(%mA0$-UxPU$5S zdinMVn!|Iy#^2d|fF+{WwGiMX8AV=W#?3PN0d|}9ev|(q<6MA28Abh`j0*rXVeiTW zcwWXV;U}YSYA%uuP$<`l@2QY6XUdnk<^dd*AOqlvX*43EFfxn-0FPxZ3|E+6@Um%K zB_he4wgF*mY`_cfjp_Hj={IWn7=wzz#Py&+vh|5}Y(~C$D{j&U&tVhtJ?C)?W<=6^ zeSGXZdT@Ya2j;7T6re8BS{=kP{;C9RvjKMS^y^AKKiPqc)I%5JgXuOcVGp+GZIlUJh)fl3= zhK3wNWa=aJ^rD5rJg-~J)Gr^Q#Uax^%!jUtxdJ^j)v`BHML#XI{##AdG)i50DN}#I z;ZP*CWS)L8O?i-GBmKfkWm8%-U09~{rbg4z4N7skm4^956Y=Y7>y&-3+syDBXjj(H zw-FbfV%be)i)~!Og_B?Jxuq2OtaT+u>zoHlh5RPD@U+-n=Nc583U5Wwy#tC(Hk>$$`^zfS6x;z$%#z*SA)*~X!<>N?y u!>hHH+N%syRIP0&wvjk>0lm3F``c|JSz)=4&4jmNt{MbMYYNG=c8bbt$o5XAi3&S~O8P0pV_t957BBf1!J@@?1 zIluS2w|(!m_xgu={Ow;Mr5;dM8qik1EF45e{KNy&Bk3@E7`TiOgLDgJIL7{JBb z;6G5}$?_J!si3J7aEef3gIiYv{=YbI4RHFPq*E-p*5BQLlYnGg0g|EcFaK&gDk4A< zQMU?+Kx1=i*!U5UWKfckiQL`;K+=uR`hajK;>(6;4v@QHfS2mMHN*NU--~B3p^IZ2j%d{vlLaS>)k@B^Lo6zqiab2?3un$d^4Tjy|CTO5`?sPTSGy_LH z+TnN657=At-7h<4DvOqQO2+>BXN*9__w3C!RELV#Pi;t1pS?P)Eq@=qNAU=-J13A2 zHL%<;8dG`@m>&v*V^`yH00ftLzS!gt*y}h}Ut-pALY>6wBjyzdoHcs^2p|QH*$51W zY&n6PxE#1aOH9~vLXRmfatB0g`6T#~&kG5$2`@(Qfu0M~UYv#Dh)xJ$FD9(|Lo}@T z0UqYLYZ}0#BJ#XZk57r12e3u2M|J*35pw{37LnI)iC75W;QB5Z-~kcyxt@sLaYMKO zphEQV>ns+rXk1ru&m;SNPv#(|Pimy7oHNj(vY|f2$ovkCcOqb(Sw2?ewIvA%Oe4c!6QCZ8dtVt~-7_`f;JVV?z zd0E>PC36bwUC{yJvb17WN2k)^Vtbb-Ko?o39_xBxAw7|>$GRq3VD0hvR_xQZt)VYH zX==qNS)+>zO)8klAFSIi(sh>naX+W-^wLVpeQdCPm@X+Y2V+!Qjfi0y7&1BS>C=u2!G8fC@9{hU diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a index 9a6e4d821c223943c18df19d9b5eeeab0926cee0..4fc8c40353562e51c807a9352869db471a808a29 100644 GIT binary patch delta 199 zcmdn7mvP5l#tBmFMkYpv7M3O(6|b_u*pnanh;J5Q?PEs~IKWfKiXspr6ox8rLHrl0 z882imaiM6rp?-`5MPQFX7AKN`#Aa8kKprFk@y%P@)YxDGn;-hjqs^HCIzT<5 delta 196 zcmdn7mvP5l#tBmFhL)BF2Il4)6|b^zK-gv$oBy#aVTbW7C;wv+-+Yj#mK9YbRwxur zK2F7{{OIoC__*N-4#bm(lX##7P!p%#|qz!;H2g&os?|Cb&IVEkbBKYq>T?lpQDa4sh5 z0VgDOxy}-_+;aiWCMW=M9{0oqF<*u`k>(3%eP=6>c(XDa2t(o*9cxN~JdX{dKwgB# z!$9Uo(g#~E012}<2qcW>ERebATo2@>kYZ>sFa=~jhU$TE0&Le>#@RY^Am#6H4i^9ob7B|J8Km$p@zL`^pf3db{(q+6>MEd| zYmIS1pfxZrE1nmeKjzzRI#w9|J4Q)uK)bKtjfsVN$5r*VBjWT{Q-^PN?d`OP6RK+a zu+OA-Dt50+);nK%HW~Czc4y11oKs4b&T;rskME1F6 zDn8-qsdjU?NZwp)7fRe^C9$TqwH4gs-~ALqTKP(+5wUCWuhjIP&A3 zJkgTtmbg>>{gHnb7Q-^rc>f;yj&;hIa_02OgQgK*mFc3{l{Gn&1%-bGQe3u4U)6M= z+mLiWnL5T2js}7Yy1u&)Db^9UR3)NJj=*P-pDX&;g755o>z0(F02TAZO3~fHms&h| zDA6=#TX!*N3zZ2Yd14Y9!@u_C%?z=n^I{+ZV%`R3* z1VwJX=|rzG?4?e5WK=NoV0I{Igeyw!WlS?OC-h@s*N5`H?sVmMiskYzV`)mhfL;l5 zSiqDDP|Vc|u!(CLz%i~ifFHP~16<;|2;df1J3x>ralkY6^*o*lu#0OJKp$6D-_JE0 z;9IV&&mUZE62JmBFi&uBWsOUjl2@3|6P$dfOj$tzR~BEv)djGQD;uzeE89TJe|m;1 zs~g~&3vh!g>z~N`GoP=+2Zz^p?%p9^|K?4(?T(<5M6@D1b#EofS9<(JzzU_@fcbL$ zT|sFyU;*|h2MxFcn-njXpz%<0_F!MB&hd}pwj`ZXJ%P3QwfxudHKQ)aau0vjS4}^_j}vq`U5_!-qI3La@`-k4 zySm*;+Ou>y3s#bc`n3wykoL%{BeeIQHjut(pKgy`^)!-9Yot%N$Dt0k5OZ`F+_}A% z^d@R@GSq$#*`?1Z?<5C`H92;5a)4}zzLj{N_l8J%q)PFQqC-6pAV;Ie!3SD3PX0>K zHClg%T#4Rh-soMVWy^FqpBK>9@dHQPPALJRU=qfcuj%dc(c#U3ihMTLburB*w789~| delta 3951 zcmb`Ke{2(F7{{OYeY^hH=;*qQ-dMMF8_I@5ZruV`lpxa_VNo&(i3AJ*oH_{*z_GC4 zcAL}$!$=qh+|)m`Y9J0Jj6<#@5E3y+5R@8bG|XiLwE{G z(dhL7>Xqon?=)aIH~RpMkHLK!KwN0FT9KA7Dm=UiEM;(0N8f z8fo6}0)7k#$^w(JRX`ZCVN9e^2Wz$fNd|8o1!5py24b+c5=acmI7p6u69)1~(C`2M zB=r0PgmGz7Qm_yX#$@`#2FD&#SEYVfV%LAi%n&Nn^orZ*v0pVa1bO*lkLs(M$r*-{ z;Xs_)xcGXe=|s;{r*%yz)pRnNu}6Kbu{zCkB0-#^b_N&POef<6@u=RmhBRYhLD?Un zX zsHnfyX^i{zsfgegWM5keIwYSRES6eCr|1(?zVL`U2JGAK-??|+DniMkb0;OIH?KWF9jpTNxeDGu4cU?$kv3NJ^g5qkiPz=xI z)FV;%cs@eJB5|G=9^mv!C4Kv0SLlWO<9%>?x+g?2Jc z*@96mx~$y9Xoljwh+N9XZtU9KihW9dBeqOM03gs0H&|f{JvRPa^kBDfLY19=Du>P& zD6Suf#mUmVdYT=+S0d?_Ou4qxD{pVNDybGUOaACunzG!2I;DIXn3@6LXX*xchiN9j z9;R6UN10{=oMSoxppPo{02p~Z^J(5Pra1uhOefN{Fs1pOOmhJaF{O3>U`p$cql=^C z5^(H*7Otdx&D(CW0No-m0i9iPs$0HB&FEwG3wU3f!W4>P5C`htA`SJ*jSfR)v! zKAVRv9G-r=adrLj6;$ij*UPu|m&q+RELxQnxe?um=p0;}QevYwU1_qRV#FyS8=9>2 zox&F7j15gfHA<8kD6HhzsjO1wF!@uCem&Xgv(SCO08ToKOK#tqo5EWG{*puMGG*Ul z7p-;Cj!KOOy+VIov{DBOWDj}y1IVMb=A*n>BfMiv&^F@@4X{^Vt9uRgX2joF=5X5U z8&GJ1;pp8!d!h}cWDQx(nA7HcfVjX1qkX@$q|%kf?%@cvj>`)QnQrusG7Di1h}EI)0N9irq&Thndz`6 zW#LZZkAEi!JbNxY+UI-88@WbM%qlrSo;3euW;@PltA8U7>rfPX2zFi~KNlF5wvJeq Gc>e_lyM-SB diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a index 8897bb075482b28000e115fb94d423441697436b..3a85a59a3b69dad1b515350aa6fe42b6be165136 100644 GIT binary patch delta 226 zcmbQ&$ULu+d4d#&k%^I^g{7(KVyM-iD^pjZl??#%+F2ylE5&{4o CIWr&t diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a index 30d94fc49d24f0c3399781ed9e9fea4432f91e89..69ed255eaa2449d2ddde7bbd5177afb8849b5222 100644 GIT binary patch delta 80 zcmdnd!?>e|ae@?^k%^I^h2=&CF-9nJvVf4p<`Bkh0#N=$1&PfXLhJaDxL*_$M3A^f Hrfh-$O!gEg delta 79 zcmdnd!?>e|ae@?^p{1pPfyG7zF-8su)6{&k9pf1RsKjI&Mv2WDLhJaT{D}$@o4+V1 Lh#+x|OxXkhJERls diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a index bb308cedafa0bc7d8d93785c3598c81c6aa34f8c..8de090342b9d86c3f051680f00800ab0cc6fd2ca 100644 GIT binary patch delta 4699 zcmb_g3v3is6uobLg;Lt>w(Kspw7YF>3lz32?QSihDa453yDcCkDpEcTYSk*n7_?6P zg!oBlNlPCjpq1b!)krCyDTK&3My18ALMa-s7$W!yg7Ft5;=R+IVRuuAF5C3%nRD)Y z_uhFkJ8!ZrZRve&=}mVG^Avd|mE7ek+0Z1|cigp(snda-zI_PL1yMnbc4Ca?sZn(u zqvBXwjc(au)_@x2b&I9}cLNBKP(zKW0T80WQYQ#eLe(d}dJu&FiuQFN#144)aBUZe{{vD+3ETo|c(CjmNCy0mfMlS$2&AE~x)h|_f*M7FZU;y=!^Q7GB3!Kt zgPeE~hJ+d!a94qRJ6Mc`46L0EGGTMzrcj3r9gO$aCrxtl7u$tAwpwdEzz#EY1%u$90vwN4h3NgLH-_k=#!zGtEbtX_TS)wyu(%br zqD~hKb1=U%ME?ko1)qi(zZzqaMMwpP$&d4253z^TO~E<>DEgq!g40M>nmqtmFcRb2ASo{3RA=4O**V-bFr)thxAd^o zxWLJ-RdPd*Hok{3fp2YPS$x(PY>#>;KmxTr4qznlaDYT&H-L>e17I|9Cf-2AI35oH za_Nr2zp=Wd&(9}4Ubpllm{QM!sQ~X$C?uW;P(qAJrXZ={1Slf|vrQw;0l1qO3(X+L zLNkf6&>UjS>LdWv{l^OH|b()B?Pb3+6^m1`5pe)(kmIq*7Gxn0U>|9We@=|e;iC}Z zarJWW28qX$@DgJarN}k7l=O9{d3EGd9%8J$5$DlTcaz3^13~{hvRX3+;1U^Fz>0TV zJgypjuZ02t4{0aB3&fakEitZU6EQZhE9f63#zyq#1?D?T8c+UwaNHlkcml2*HBdl| z@gfn|EFPDwoD9UwV8Bo8!m}bC%O5zw-WyKKj{lIsE4B$~a;5|@n?Gh1v)QBEf0E@1 zRSCRd4a=1u!@IARuXiXZJTOPH2&a>ptFPI(GexwpGyF0QJ(JX2QDozFXvt@i09NxI zCs+!vn~TH!7Jjae<+3*3)W`DV4!X^nznz=S2KWFPLZOvgp2v7OFFb{^(aM*Se2X`b zykg}YC2qaUVle?7DDwo%y2eqM*35|6iAK5M>QnI(8e@k9MM zY04=6Lq9Wj1TQai%MQ(Rn%$RYKJ#}s2?r;ds=4lvO?%uecoGfE$2)Ae*&LWEOv<|9 z>4_{$g$85O^ajUme^uD-GRBqY>7H*F3Kp4`*1^QBsixFN)Y-%ZmT>F4T(LF9*xc5; z>{@H7ILzEN$=E+ntV;|XF>{Idb4IAKpkCaU88m$Q7OoX+5fx*{4qE;m@v2eDr{P9F zIW2t7)@x#ovCsNA?ebb~hV-uSDxg~q?WZznp0S7fG#qurVx~dm(6Xzg3pWPfmVT;A z8GOBHVGd2{mO9cy^ofg7ZL+CHYY$zO7N?rpq4g!om1YN;+bzE~&M2oHSS&wS5L`}Q z5w5UZo3d73X)~a_ujFITi1@ZV-MOf${1rU2wOMfWX9l|ZHS1A@`y5okU5YLBY}%= zh(=j9cGRGP8JJ8Vuu1MjvIi1Ll*h(P2MNL-3K%pUi3qZQ-`Cz-+hq_bZSw2ye!ug* z?m6e))AYoq%*IWb>qjO`EGhB%{3W8hlsk6%KVTXF>$`JEumWO&7HeRf;549}3z~;$Us#0PuL@pbI!cqpv8O^#i{Z z29^Q84aixS;TF)M2g`PYY@#v`WE1l)fjktJT><%ypv92j#}gpm4Ck9cCj3(v1toba z3<+)UfY%Pno!}WPWa8~4PzW2}zbUjK2Rjad5)b?_0Ez*1@Dzi~2z0eho@g0zzyPRx&Sg6Cw`uBELm&Va#WwmyXx<=$?llyAbVX|1gm_l>`=-{4T$D>@IbqJ@)t+xx94_x2{bLV8h;&E;Iia@_CALFM|n zZ`QT6)<1CK$laq|XV$36$JK{>uB3JC>4%hIJudCBX|1h^?lTYld=5IX2iVs7%8U8a z9+^hj+E+rt;p6QuDr*kt)dv}qc!H0M`G?sNEf-gY+{XdjO`HgjOk4l$LrzlfHN z+Fe2d7J7+T^v`5oaca9fTnd1`wwL|IG%P*?hwe%McojJbn`}gu@RoOzjpIKMV{=yA z3`v+gml%uF=BUA`qvwnK=aG)_ZxUn84>69Wmi8s(q5VkuG31&ofYZntC6;h^CAmWn zk~AJ~glwF~T4GGNf*5CU4KX&*Z0KJTVKFk5n>T zEG_09bvo|1XL-|fIY(+q5#1dH1Jq4hyVd+tu=*d?sQnp2;Hmi0~ zHy({zi|9vRWi{@sJhA2~A1!T7jTpb2Dp(2TRIOt33DqM#WffIuD+_R`XNb*X&|k+P za@lVcy+_f-X%kh~m|XO8ox-&(Y5$;GwX|x1R?oSkVPFO=XyFRs3v3Siq zxZde{-JeQ(L4@Mar)8)y0gaQ?S(BrsVGGsT31KO?12#0OS>fracRTgoX0?2Z NnLD(UzLTn_=wH-4{N4Zn diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar index 0d0432c2ccbaac854056eed70ec7fa30c91d8e9d..a3d9f8cba6cb0d4e3a2187fbfb452e35b169ceba 100644 GIT binary patch delta 189 zcmdn+jA;W939)h*nHU*b8W@^S-sdg8*^sqX09izA^BGYi9#jz-rAu7wP+gPv0yXjI zq6z#l-z5xFv3aleQ$ZL9s9a+6!PtjFNCM)U4;09Wq6qwH-Ng;F(_-_!i4xKX-n}(J FYyglvI}iW> delta 191 zcmdn+jA;W939)h*T3Q+yn46hT-sdg8*^sqX09izA^BGYi9#jz-rAu7wP+gPv0yXjI zq6z#l-z5xFv3aleQ$ZL9s9a+6!PtjFFcU3-wu)^&P#`CYD)Ogw7dKpF^S+4^(g@zY HH9>3uFnK%` diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_hci.ar index fc3e70f00ee8866a0729f1c6886e28a2e50de80e..f3ad568c174f7cfc1a07dcc51660442c53846dc2 100644 GIT binary patch delta 134 zcmeBs$J+Ofb;AX24kHsILrVigi^&fjh;4qyy-o*JWS50f15CsctmfB_d+KnJ%?}G0zA`6LaKb6AhA_M>>?=V>a delta 134 zcmeBs$J+Ofb;AX24ns>z0|Rq&!^saGh;4qyy-o)vVgwf1Wuer7D)MW`J$0Cf@#Y5) j3bNolkdEzn-i(*{k%h#!$44{zav}?fZ9kR5=pqCFG=eaX diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_sec.ar index 367ea52db67ef8f90c569e2c74cf6cd38058cd96..c1493a5cc8939f557f16ff19a8f9c4364b4c873d 100644 GIT binary patch delta 75 zcmZ2cxuSA|86$_0iIJhDfuZGQJH{h?aNcA)M)A#x0ylY(MZ`8s$g&9_i->Qw)y?Jy E0QsO2mH+?% delta 75 zcmZ2cxuSA|86$_GrKN#^xw*+^JH{h?aNcA)M)A#x0ylY(MZ`8s$g&9_i->Qw)y?Jy E0RL0CjRAM4qe?YYGqYqt5mjBvR_(8#R{TK>ks_Rx_h55@8xx=%$UG8=iSda z=ljlm$xS*3iXIIV9sLQhK0v24pzD7CN=Gc6rVRG5w5HD704%-7mazd?nx9)51K>bD z{6{PqhRXq`qZM_4(-borw^P9XSM6Sj2K{=o zW%7_T$%JA7&=PujA2d_CXCIhiiHpp{>h++%lvs*}9dXc=ng=tZuHB%Iq}d}SUd%f- zW*rE*qBEnBdF7FL9XT^xMWddtqWn$?_IAu%elhGM6L*fA!6MN8bJLl6HMA~2`-;7<2o(-=J# zVv0b>^~0E8IL0r1jVjT2UUUR8es~AI`T37%l=$o$bcA9z;%{~!FIvS{cc3Bm0D<+Q zaA)XV(i#B4pjccP94Gx$^gN#n7XgG- zoxIOt6-%D`vaCXYeG23QTriDps3?sLV;{gXwU&m{%^NH*jhD)Z1H(2Tjg1ZD0h~4c zE}DL~Odn%VIhcGN1aOg9DNs9V4d1NgvAKGi=stm5i2rgDy^r!+Bi$ap^b~TVK3=s6 zdwHX}?&rHsp()zJ(Q*^5SC$1)2k(`D2V#_>4DG!Go5G(?#kxH3+ZGOsvD4_UX^tZ&E?h^&b1a0aQN5=m>CG-}c&YN)M^ZG9w6 zANFC>50EvvYTJ}5{a{K7$s$+c(nw-bqr_^8jkb-IKvLRNR3s?YO7C4}hMny~>bfMq zJ#+r&p8q{FvwOKeobDe^@BALAt$=!?z{ux-B0-I$DT+O6L{mp^05!757PSG?2;W-- z1K`Z7@E_D*F?$?vB-AYh93g6;@$GYf|1U>20gfJOG|j?$O;!L714-BfBthjL={L;e zHUJ5wYy^m)79wLO-zOYuI5AXfE&~#6`VIr(sN%!KKtGVVxa9)!7)Z7Tm;=>ZbT@*e zQ#t^W&W3i7!m;@;ke&!N0t0pkq}llKK1hP017;@p&4fb@5#`hpcp{$Z0$FFfA7sHh zZL^|=Egs`0(cp(+kahk(1+s=E`8m)~^^54lY8O}@3pGr`zQbSi9qm?pFSQ)`zm)=lHcm(Irp7W$)eXsfI$EZV@}fv1qZ=(7cWf3M*fUF1zMw zgL)HIE6lwS`K+a`)yB(Dw2hIBysoqbnPq4NQ^o@ic0Il~S1y#}QJ~XBNj==bn z;Lg-=P!51#kmnVKhQM6MfqJD;$02nRs6Q}vAaLGT%l~r#Qo&~uFdR4K1X6->-~-N> ziSc4!&@dOd1+;)^0K1lXX>5mNweh{)?>B4z+sxPP1-V2Oxn+)u=$>4ESffE=-o?^7Y7 zW7=1ZO9l8;2+08bn$e#ka-)E;0`O4e+;Ek)L5XI(o=2P+as%ABUGwp4K3BE=+amIT zgr6A51Hj&A=n$gEE|O~YdJp;x(fHHoWdwBBX_SS|(em|Jq3x%U4fhjo)3xPtb}S#< zJ6M%PJ8iOr8pWkNKMr6Uze=Vxeq@t(^VCMS`nkga`hg#!;hBBH3@uInouf< z%0Il~EgOqLv9u+JWTG}&+lyAnU3|@#H17n;k~dlb)_LnMWZ`C;ceFN*{?>~YXg?~C zck5k+#eavcuQVw!e;`MZNvT+jAI&!@TXJwxmPu)@!yoED*J6*h$XoM}{Y# zHdR~ftfQHD@^pW8vybE^Yo~}O-)rS(Pw^G9Zjm7|erPQX@^I|I3hT2;lbOa6x@s}k zuDPYE1tD5_nbc$49z%6fv2kate2ete3;G;M&NM-k=YKPv)xU}nOJrg}?Y)Pp+V!U~lxI-RX7`#AXws+;RnPO$1e> kuVS4URK(l>XpZ>i==Ggk$Rc8!nRcV6vxkbp4%5{fl?~1P@oj1M7s=;xS~!SX|9Xe2SSK3YK%s*F=za+DVfoE zJ0va(%!n7g?&X7HE^fLHVu_s@i)`-27?-pL{2)lkjKfG|xVTss&^^!9zTBpmS=;1y zPoMw!pYy!j-kWxvw+x)O94s_e*Hka`*4Dh- z(DXTwnUS=~mH{A9_5zS7ZT&z}(a{LxxnR%#GdJjq0GWwP%|JL|w(CTO*gUC_lEv{R zAkP8C4G_cA3zW0swHc98ChJ2$GeNTeG)k8TXp|FsfIdcwe#uO{06?D!DMi6`A5hMX zZ5ctJn_xy3KP@?P?$AL zG-TbKMID2>Pr?!N!E<*Z*BbIlD3il*1j_5gGV$W7w;}M|U2Co!4E=(-g6@!>v-5#@{R^d)5n!6uwiUhJVovU$vWgrY_9Z$+C@IZ4g( z%6DyY*FVm@RscYTmtCx&2SwgBR*F5!U=J-__{)=|Q%xG-8XHGH7WQQ#I$)8H|5d^i z8{{j4`N}*2dsaXR6HR#lRXkb&*6^4Q@F|ZrfPNll16<{?0N@snc7O?e720`&68%5L+>+L_rpdEUVzYg5A_DP}s)m+}p=$ov&NvixEmT>z_j zv?&MJbj8fp$A@JAfAYxM>3KV*J5ZU}h>PSqhqC4VaUrPJqZM&V&TB2#Z889?R9-b; zIaVo~&r`dy$AA_*rhII`dAeo-;8Z$)!+hm3mm|t`CS#l2Ib>IyMzjz?kSF%d)q4d1 z7g3hqM7M6O9zZAOtt;29H3EDlmo3j%`iy8z{IxrRcZ^s&J5jO+eI;1(idOQk#{;qF zQ+-T=o-H_%7j*^M({-*OHVU_6u`N1!Y&Rdn?i#Ihc>uR&X{E*y+?X^^=qAoLYF&;A z{57d?>OSt(X$=rP8shINwb$B9 zq(DZp1b@_(K-?`dejpO86{I;vE*O4w+pmiPh(3YePc~{V_N!#wPrvHpR`Qr*;f3ANI$myv}2$Hr1;-U;R&{xl!3?$h++75)F@XK9Hx&h=~JlhE5 zepoOY$iOIf4=!5=#9-wiAO@>zfW)KD4dj7f@Be)lXo&zBh+{=SI8nChzMN+B#6#&X zb`%1600hhilj156IFE}1qQo7ns0Se#y!;Ia2I^H147NW8!YvfzCOP)&Lm=E2N}PnV z77#cWij#sx@WOzMyVu~rV{6B|wVFZi6y5$UQx?$DOS;qhc;yuy(^EI?leCpHf6Fix zEgX&vGQ6?cBg^LwHa%M1h92$9)z8^YNezc3Ex&H58C0TeqBHt^fhbo;HJU1e%dQ>OODnZ;&8sn+>tLz+1}dU+;}Rh5||ajzQf$yMqt9YW!| zySMGBk<(vAg8oIN=Cp+@F_U-;XE425839c@2$gVv((VgWv z(KUAawZTGGt99cKl}DRV_l}Vyk=V^NYqb`{a~-o*tRfemPSfCBIt9L$wuIc5Kxub82{@)M$#AtAZSC z&hU}fSwRQ-EHTZ#`@og1Rp>pU{oK1sz;pC`SQta=2rj^OdW~QiEj*77TGL7#RIDXl zwf-N=Xas;DySTsx@3DL1<6t)%42N0nH_>@7kUZ-Dn^Y~N_~C}z-9k;xI7BjN~LtgbmN(b-(NN}sF{M%cU- zw&{dcUqqkPZv*(3;(RQydPIOv)clDV^oEEo^IQGtK94>+1w%uP7o$`U=VIvu)1}On z^si>&hjue*-WiX+WImpC8j3z`DefO;dd@n`aT^}3Jw`nG(_3(BsVO-R5J^vM#aB{H zDHgT94duVAc3+H|tjtP!LqiUp5;Vgd2E%uKy=87VYR zsnD$*3{;b?HX|eyJIwUIR+FkbaeBCpH2Teu*!&|8kZEbAL|I{v{_!#5zLUkzK>c`> zY&1I$>1_F;vGSl_ukIjS#`6vOX>KL!_#+g858p1#Lf9(mj0FV!v2`wgTv%kRlS%BX z)^VCJ)Hp#|5-a2_HfzL^=ByI}#sSKb(#s`%*LGo{vB|fkz+vGb^Y5--fAOr~HMWLF Zlnm1wF9<*78Knc1Jt#?EBUmP7{|Ch4hV1|V diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a index 50309c95e4abb7b5be81bb884b3986e877a1b9fe..66636579d88e49919a670c17476efda996880a48 100644 GIT binary patch delta 226 zcmbQ&$ULu+d4d#&k%^I^g{7&<{@J0lRH-fpXDgzp8tiwI(0p SMv>XfHGi8Vs>r<^2iO6&`9=!> diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a index 619acf074c1503fa91514b2c674acc7575c1035e..1798b322929b29c17c81496360f3fadbcda927e5 100644 GIT binary patch delta 148 zcmdn;n03oz)(KJ^MkYpv7M7+KlOL=T+i2mz%?=fqs3^X99``hLm;y79g3Uq3ZPjp* r%@5Yusla&VV0oL%DS0pvu#wyMIWk@mL>1Z)%*euxDs(B1@sSV!8458s delta 150 zcmdn;n03oz)(KJ^hL)BF2Il6blOL=T+i2mz4HGa132dInJxv`ZVgeQkGH$Dei)?hA diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a index 4a762ad7091fe43a461089e5f664745686df5f0b..e9a236a209cd61142b1431215fcdebf469141e07 100644 GIT binary patch delta 88 zcmdnd!?>e|ae@?wk%^I^g{7(GWIIN&i5CB0e2dL?jAsPkJdo^W4WV^>FcHhm_Y}-T O;5?wb_-12MRzUzWh!(~G delta 88 zcmdnd!?>e|ae@?wp{1pPfw{TaWIIN&i5CCh{LOZZX9VCpknCm+p>=$4k>RTLVfsj9_Cz7buZnt`n39VfZGl-Ve(EMe`e=L=X7;k6y9? zb8+@73<%pM;5Gx_vMr$~ItV-*GtL7i%vl~8R@4F?2*yBWxYslXc(l>E5;(%3w-B6q z3;6Z$&$qyD0BUMETn9#I@a`#~nke}YR1+07pbmtkwV>V{+>#;k+_6yO$@nX=g1@E;2*Z141;+#3b4>OL2ot}sN#<)ht>}{E2Cpri9 zKkj(ljrEGXZPf!$xC4%`7&vI~tGl!Ov%F$at(Mf**Sy+h4$5n*?)Yg$KndsFs-x|> zqi+unOsTl2+1rZF?YD(EyB(}P)RCXsnAc?vYOGTnGP#gFJIc&GwxPPiCU;e^StCs= zUt))af$rA1?6PtPJDFrAK|}L;^YWbHm1ZTIEtPfq*a2od&cOfDLEzQGAiWp$h9G^= z9E!}r0^cBS35tIg61T!O)G3N-_UCs7>GJ^T@L7=Yi#ZmVLn1Itepvj{!5%d>`s*m5 z`v!gPpGLYY&;x)KqZMJgDoj5grdNgObz!=Rf#^EGMzVHsQsv3UaIEoV*qHCb^!YIT zcbFa=xNQK+mw@^!#3sD9;yvZy^;VpdgCIQt^+t>V_Oc|2PZvLP7Ap^b!Wa|9Hf@kT zuXz4*^Q+|HgKSq!=A5p-Uve6)trpjnKmNVKp}f2OCD64Vr$Ktqp7@N?KJmsO=AAmW zyZw?izNkCa**|hzSAx^Agr&RIsy^r6GkexFx2~IfN&>n3{*Pn^|_g;ed zm@cO=?cUbbSXbYDy=R1_lO@J<^|UY4YC7fZos21B+nX$1O#6y`Xxs`ggxbFiU?_1c zz%b%m02^^CKoW5pZW&@6kCy;hv`6qY%4hlJ=a9bLXZey~N?#sK1-L80O*{smkQkGU zM>4<(a2FYvZ4z-Nz&*rR=ssdBG?f?&O(({zCB#^$lsFNfj2IKoB*w1GiSGb-gqQ=& zCB}mDh+P1c#2Elj0Nmm$P(=o|zlazMEg^2)8j~v~cC#T0FnNDB`;8e`n`#Y?0eBHP z4trdWtYiaxL>l8?5Myu0iE;5Vai7HDJ$Q++ha%)kTuJ)-rg_!mQyyY0y#eRZN*^MP z`TG3+X=I~vB)~;7uz(deUK}nO{UIx(0X(Fg0520`!dhZn%z9#M-~+#ZkQf{BeL!Ho zlce$9Py5IH?vD?_g`);W6JtD|l(yHSRq>9q* zO0u4&0u(D^*9o4^o)RTJEL$lbA{PIsWob|2?yC}Yd$bJYSiI;!i=7aqr&YUXDdraQ zI`;^(XeZ(UmNu03B)mDDTa*%uICX?&u`Qzh2+P)5XoEF;e}4w+6MbkXZmVEtFxy1o zK8mu=DoROi7BwUE= zPRn5pKbNH|o)My>7iWzhA&$?9CiJuKL= z%a120p7c;_*j#0$c{qA~|LMzJtCg0(@zZZDZ&s$vG!L6XJb&!+2gcVX26Cn0X(wN| z@dqrS)|D*Ym=HR#t%%12&PmE;lf5(evOueJAj>D`@C&JCDxb4#1^*~5#3^p#x;w~m z$iN;LD2 z6)iSwJR@E!b(%AMPXP_N+Tz=SoFth!OS@;ZIWJ#U*J{hn2aZE1zD3^?BP&1~+V^>3q8IAtoHEP22p(y>n-M!atCQPl(%x{19`+d)Q&$)Yc zvU5jTA~U3_^6ummE48fjvb^3;f?j#6{%tw#3P zqBejU;krdKfGZD#=1@b0K_7z<38r2FAwsDB#C0n{_`j$e2}1OM>mR*hE!GlQ4YUaB zWDu#tAQDOjM1~c^Kx_$WOJZ|vYZ{2r#_1s-B2@Ya!_`S3J`ayR z0r3SO*{$##sNv4R3P?JN7K5atG!LYfuxJ=aF9kJ%0;keJdKPXpfkb$)Gz@b5J!lbX zbBF6KkY5IGU?UxCCxT4);?gsrw&<*H4{|hcX9UPWD5(xGkTVyQ095@VI$ZV}C@%!H zg@nyG9bs2xbZ{vSlxLyevmDRYYv;r{vSNZiW_aOlmR#{o&YMa=D0d{+cIq?45&W^! z-%USuYFCe&ooy)Gq%vD=>oxl`4GDv6wZB%bx9WKyOgY*u(DidsASXHyV;Vix>Pams7>2f%8EPa$`;0KTBgd< zGsBd!-Rw$Au)n(xFTxua`sVVg5;2SQ);89&V@w^-Ao!;M$E!&p_F=Twh1kdSP-GEI z@DuW;5dY;czZrI--A2&GKz&n)eG4ER4u%N#^jKsOl7M0H@AY-)$~!9D^g{-8s_ zG_uE5%--u_i@8@4UF>sy<{0akzu%Y(AQ3YThuCJcz0K^)&FtIUWRX*QQmTZl>Ji)U z+KlZ|@VXqsvk+wWLi;oHHF57wxsW%BELOYn17nO|`jEwIkB+l1W6Tr150^RAni`Yy z$={Ekh*0F?^`}_BnSFf+@0t?^`eGdcy`R_ONM6X&of{;-^7#6p^_4Z{Lob|bo8f3& zrNp0CMtJWh9XWg#5?Xm3>T3lxHL=dd;lEsmdYl3F*1R{XTfr*@RPEq0h&g-y;4FF7 zDXsW4V}clyE%MT{?3~&OSBAp70<L{h;CkVirWKt3@x8b*v&hZAF?SBbIFC}M0h znm7rdkQfV(C&p;QP17^f~H#`^EjveCG6NWez(i22>|%*Ah= zWo?8e(AN3bpG?K(W6{+*24E?291gh|S-@MaBOCoEiE%hHZiYB4-ia8S)8;6{M@R1$ z#ZMz0^Vbk#&rdOr9xd%lszdvc^akXz4ggn>RVpmt?uv5;UL>JA-U!+F80QjW!6n4_ z6ju@B0K0e|{{_W@XUN8zZV1L*3;G`s;{a*+m%ZQ(^WsY{r&|AtW6D@@U9F#*UGj7 zc|uNln4%R;6ISbI9Ja$Ct!bT5<Cn9{yTTx^W$kNLJlyloGQIj};k>!>T`&J=CaR#D1+ zD%iA|)8Yf8Q@PWooxCchrG`dG|B7YCt+{!XmD#lQcFCuo;%;}~KHeWJ73wFj+pXcD ze9XA5U`TbTblnK?X!w*aObWL0(0OdrHlLEJ(hR9|u#}=rzbVa5G$eo2?FUkEQmB-y z%}9{PICRN>YB#v#h26rG>BVwEj}RqU`*E#2L;sE7=^ePYQCnrFzTh7JY5!5ZY;x&& zex>e?TxV25C0VOTRa~~ Date: Fri, 20 Apr 2018 15:47:17 +0100 Subject: [PATCH 124/274] BLE: return an error when application tries to turn down encryption. --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 6a3442b71e..fb21dd2cf9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -392,9 +392,8 @@ ble_error_t GenericSecurityManager::setLinkEncryption( /* ignore if the link is already at required state*/ } else if (encryption == link_encryption_t::NOT_ENCRYPTED) { - - /* ignore if we are requesting an open link on an already encrypted link */ - + // Fail as it is not permitted to turn down encryption + return BLE_ERROR_OPERATION_NOT_PERMITTED; } else if (encryption == link_encryption_t::ENCRYPTED) { /* only change if we're not already encrypted with mitm */ From 27d36ba820c6c3e9e0ad52e4ae752d9dcf06ff97 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 17:07:54 +0100 Subject: [PATCH 125/274] BLE: Add missing relational operator to SafeEnum. --- features/FEATURE_BLE/ble/SafeEnum.h | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/features/FEATURE_BLE/ble/SafeEnum.h b/features/FEATURE_BLE/ble/SafeEnum.h index 0f9a0a5554..eed1b8b7e1 100644 --- a/features/FEATURE_BLE/ble/SafeEnum.h +++ b/features/FEATURE_BLE/ble/SafeEnum.h @@ -139,6 +139,57 @@ struct SafeEnum { return !(lhs == rhs); } + /** + * Less than operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is less than rhs and false otherwise. + */ + friend bool operator<(SafeEnum lhs, SafeEnum rhs) { + return lhs.value() < rhs.value(); + } + + /** + * Less than or equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is less than or equal to rhs and + * false otherwise. + */ + friend bool operator<=(SafeEnum lhs, SafeEnum rhs) { + return lhs.value() < rhs.value() || lhs == rhs; + } + + /** + * Greater than operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is greater than rhs; false + * otherwise. + */ + friend bool operator>(SafeEnum lhs, SafeEnum rhs) { + return !(lhs <= rhs); + } + + /** + * Greater than or equal to operator for SafeEnum instances. + * + * @param lhs left hand side of the comparison + * @param rhs right hand side of the comparison + * + * @return true if the inner value of lhs is greater than or equal to rhs; + * false otherwise. + */ + friend bool operator>=(SafeEnum lhs, SafeEnum rhs) { + return !(lhs < rhs); + } + /** * Explicit access to the inner value of the SafeEnum instance. */ From 7afd01d84d893a28672e5dae12e7c56b7fa47c19 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 17:22:21 +0100 Subject: [PATCH 126/274] BLE: Add type describing ATT security requirements. --- features/FEATURE_BLE/ble/BLETypes.h | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 41e4c99f13..b6fc3d5c9a 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -460,6 +460,74 @@ struct random_address_type_t : SafeEnum { SafeEnum(value) { } }; +/** + * Security requirement that can be attached to an attribute operation. + */ +struct att_security_requirement_t : SafeEnum { + /** + * Number of bits required to store the value. + * + * This value can be used to define a bitfield that host a value of this + * enum. + */ + static const uint8_t size = 2; + + /** struct scoped enum wrapped by the class */ + enum type { + /** + * The operation does not have security requirements. + * + * It is equivalent to: SecurityMode 1 level 1: No authentication, no + * encryption and no signing required. + * + * @note This security mode is not applicable for signed operation. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK. + */ + NONE, + + /** + * The operation requires security and there's no requirement towards + * peer authentication. + * + * @note Security can be achieved either by signing messages or + * encrypting the link. + * + * @note Signing is only applicable for signed write operations. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM + * or SecurityManager::SECURITY_MODE_SIGNED_NO_MITM. + */ + UNAUTHENTICATED, + + /** + * The operation requires security and the peer must be authenticated. + * + * @note Security can be achieved either by signing messages or + * encrypting the link. + * + * @note Equivalent to SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM + * or SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM. + */ + AUTHENTICATED, + + /** + * The operation require encryption with an authenticated peer that + * paired using secure connection pairing. + * + * @note This security mode is not applicable for signed operation; + * security is achieved with link encryption. + */ + SC_AUTHENTICATED + }; + + /** + * Construct a new instance of att_security_requirement_t. + */ + att_security_requirement_t(type value) : + SafeEnum(value) { } +}; + } // namespace ble /** From 9258b9ddb69f18eeca953f67faf6e102154f43b7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 17:26:15 +0100 Subject: [PATCH 127/274] BLE: Add security requement support into GattAttribute. --- features/FEATURE_BLE/ble/GattAttribute.h | 108 ++++++++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattAttribute.h b/features/FEATURE_BLE/ble/GattAttribute.h index 59bb7285bc..b9c6c32e66 100644 --- a/features/FEATURE_BLE/ble/GattAttribute.h +++ b/features/FEATURE_BLE/ble/GattAttribute.h @@ -72,6 +72,9 @@ public: static const Handle_t INVALID_HANDLE = 0x0000; public: + + typedef ble::att_security_requirement_t Security_t; + /** * Construct an attribute. * @@ -102,6 +105,9 @@ public: * true // variable length * ); * @endcode + * + * @note By default, read and write operations are allowed and does not + * require any security. */ GattAttribute( const UUID &uuid, @@ -113,8 +119,12 @@ public: _valuePtr(valuePtr), _lenMax(maxLen), _len(len), + _handle(), _hasVariableLen(hasVariableLen), - _handle() { + _read_allowed(true), + _read_security(Security_t::NONE), + _write_allowed(true), + _write_security(Security_t::NONE) { } public: @@ -209,6 +219,78 @@ public: return _hasVariableLen; } + /** + * Allow or disallow read operation from a client. + * @param allow_read Read is allowed if true. + */ + void allowRead(bool allow_read) + { + _read_allowed = allow_read; + } + + /** + * Indicate if a client is allowed to read the attribute. + * @return true if a client is allowed to read the attribute. + */ + bool isReadAllowed(void) const + { + return _read_allowed; + } + + /** + * Set the security requirements of the read operations. + * @param requirement The security level required by the read operations. + */ + void setReadSecurityRequirement(Security_t requirement) + { + _read_security = requirement.value(); + } + + /** + * Return the security level required by read operations. + * @return The security level of the read operations. + */ + Security_t getReadSecurityRequirement() const + { + return static_cast(_read_security); + } + + /** + * Allow or disallow write operation from a client. + * @param allow_write Write is allowed if true. + */ + void allowWrite(bool allow_write) + { + _write_allowed = allow_write; + } + + /** + * Indicate if a client is allowed to write the attribute. + * @return true if a client is allowed to write the attribute. + */ + bool isWriteAllowed(void) const + { + return _write_allowed; + } + + /** + * Set the security requirements of the write operations. + * @param requirement The security level required by the write operations. + */ + void setWriteSecurityRequirement(Security_t requirement) + { + _write_security = requirement.value(); + } + + /** + * Return the security level required by write operations. + * @return The security level of the write operations. + */ + Security_t getWriteSecurityRequirement() const + { + return static_cast(_write_security); + } + private: /** * Characteristic's UUID. @@ -230,15 +312,35 @@ private: */ uint16_t _len; + /** + * The attribute's handle in the ATT table. + */ + Handle_t _handle; + /** * Whether the length of the value can change throughout time. */ bool _hasVariableLen; /** - * The attribute's handle in the ATT table. + * Whether read is allowed or not. */ - Handle_t _handle; + uint8_t _read_allowed:1; + + /** + * Security applied to the read operation. + */ + uint8_t _read_security: Security_t::size; + + /** + * Whether write is allowed or not. + */ + uint8_t _write_allowed:1; + + /** + * Security applied to the write operation. + */ + uint8_t _write_security: Security_t::size; private: /* Disallow copy and assignment. */ From 1c1835188526749371253476541e9d517e72e600 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 17:29:29 +0100 Subject: [PATCH 128/274] BLE: Remove unwanted documentation block of GattCharacteristic. --- features/FEATURE_BLE/ble/GattCharacteristic.h | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 671665f4e5..4c2195c1fc 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -72,25 +72,6 @@ * GattServer, a unique attribute handle is assigned to the various attributes * of the characteristic. Clients use this handle to interact with the * characteristic. This handle is used locally in GattServer APIs. - * - * - * - * - * - * - * - * - * Representation of a GattServer characteristic. - * - * A characteristic is a typed value used in a service. It contains a set of - * properties that define client operations supported by the characteristic. - * A characteristic may also include descriptors; a descriptor exposes - * metainformation associated to a characteristic, such as the unit of its value, - * its human readable name or a control point attribute that allows the client to - * subscribe to the characteristic notifications. - * - * The GattCharacteristic class allows application code to construct - * and monitor characteristics presents in a GattServer. */ class GattCharacteristic { public: From 486a3e020c2bb86cbec42a37cda78e73128a9480 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 18:55:42 +0100 Subject: [PATCH 129/274] BLE: Add fine grained security to GattCharacteristic. This patch adds independent management of security requirement for read, write and update operatiosn of a GattCharacteristic. Requirements are defined after ble::att_security_requirement_t that maps LE security mode 1 and LE security mode 2. The functions requireSecurity and getRequiredSecurity are deprecated as SecurityManager::ScurityMode_t does not map well with LE security modes. --- features/FEATURE_BLE/ble/GattCharacteristic.h | 272 +++++++++++++++++- 1 file changed, 262 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 4c2195c1fc..4dab87184a 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -72,6 +72,24 @@ * GattServer, a unique attribute handle is assigned to the various attributes * of the characteristic. Clients use this handle to interact with the * characteristic. This handle is used locally in GattServer APIs. + * + * @par Security requirements + * + * Verification of security requirements happens whenever a client request to + * read the characteristic; write it or even register to its updates. Different + * requirements may be defined for these three type of operation. As an example: + * it is possible to define a characteristic that do not require security to be + * read and require an authenticated link to be written. + * + * By default all security requirements are set to att_security_requirement_t::NONE + * except if the characteristic supports signed write; in such case the security + * requirement for write operations is set to att_security_requirement_t::UNAUTHENTICATED. + * + * @note If a peer uses an operation that is not set in the characteristic + * properties then the request request is discarded regardless of the security + * requirements and current security level. The only exception being signed + * write: signed write are converted into regular write without response if + * the link is encrypted. */ class GattCharacteristic { public: @@ -1257,9 +1275,40 @@ public: * defines additional characteristic properties. */ BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES = 0x80 - }; + /** + * Indicates if the properties has at least one of the writable flags. + * + * @param[in] properties The properties to inspect. + * + * @return True if the properties set at least one of the writable flags and + * false otherwise. + */ + static bool isWritable(uint8_t properties) + { + const uint8_t writable = + BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | + BLE_GATT_CHAR_PROPERTIES_WRITE | + BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; + + return properties & writable; + } + + /** + * Indicates if the properties is readable. + * + * @param[in] properties The properties to inspect. + * + * @return True if the properties has its readable flag set and false + * otherwise. + */ + static bool isReadable(uint8_t properties) + { + const uint8_t readable = BLE_GATT_CHAR_PROPERTIES_READ; + return properties & readable; + } + /** * Value of a Characteristic Presentation Format descriptor. * @@ -1308,6 +1357,11 @@ public: }; + /** + * Security level applied to GATT operations. + */ + typedef ble::att_security_requirement_t SecurityRequirement_t; + /** * @brief Constructs a new GattCharacteristic. * @@ -1352,13 +1406,21 @@ public: bool hasVariableLen = true ) : _valueAttribute(uuid, valuePtr, len, maxLen, hasVariableLen), _properties(props), - _requiredSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK), _descriptors(descriptors), _descriptorCount(numDescriptors), enabledReadAuthorization(false), enabledWriteAuthorization(false), readAuthorizationCallback(), - writeAuthorizationCallback() { + writeAuthorizationCallback(), + _update_security(SecurityRequirement_t::NONE) { + _valueAttribute.allowWrite(isWritable(_properties)); + _valueAttribute.allowWrite(isReadable(_properties)); + + if (_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) { + _valueAttribute.setWriteSecurityRequirement( + SecurityRequirement_t::UNAUTHENTICATED + ); + } } public: @@ -1368,10 +1430,120 @@ public: * * @param[in] securityMode Can be one of encryption or signing, with or * without protection for man in the middle attacks (MITM). + * + * @deprecated Fine grained security check has been added to with mbed OS + * 5.9. It is possible to set independently security requirements for read, + * write and update operations. In the meantime SecurityManager::SecurityMode_t + * is not used anymore to represent security requirements as it maps + * incorrectly the Bluetooth standard. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "Use setWriteSecurityRequirements, setReadSecurityRequirements and " + "setUpdateSecurityRequirements" + ) void requireSecurity(SecurityManager::SecurityMode_t securityMode) { - _requiredSecurity = securityMode; + SecurityRequirement_t sec_requirements = SecurityModeToAttSecurity(securityMode); + + _valueAttribute.setReadSecurityRequirement(sec_requirements); + _valueAttribute.setWriteSecurityRequirement(sec_requirements); + _update_security = sec_requirements.value(); + } + + /** + * Set all security requirements of the characteristic. + * + * @param read_security The security requirement of the read operations. + * @param write_security The security requirement of write operations. + * @param update_security The security requirement of update operations. + */ + void setSecurityRequirements( + SecurityRequirement_t read_security, + SecurityRequirement_t write_security, + SecurityRequirement_t update_security + ) { + setReadSecurityRequirement(read_security); + setWriteSecurityRequirement(write_security); + setUpdateSecurityRequirement(update_security); + } + + /** + * Set the security of the read operation. + * + * @param[in] security The security requirement of the read operation. + */ + void setReadSecurityRequirement(SecurityRequirement_t security) + { + _valueAttribute.setReadSecurityRequirement(security); + } + + /** + * Get the security requirement of the read operation. + * + * @return The security requirement of the read operation. + */ + SecurityRequirement_t getReadSecurityRequirement() const + { + return _valueAttribute.getReadSecurityRequirement(); + } + + /** + * Set the security requirement of the write operations. + * + * @note If the signed write flag is set in the characteristic properties + * then the security requirement applied to write operation must be either + * AUTHENTICATED or UNAUTHENTICATED. Security requirements NONE and + * SC_AUTHENTICATED are not applicable to signing operation. + * + * @param[in] security The security requirement of write operations. + */ + void setWriteSecurityRequirement(SecurityRequirement_t security) + { + MBED_ASSERT( + ((_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) && + ((security == SecurityRequirement_t::NONE) || + (security == SecurityRequirement_t::SC_AUTHENTICATED))) == false + ); + _valueAttribute.setWriteSecurityRequirement(security); + } + + /** + * Get the security requirement of write operations. + * + * @return The security requirement of write operations. + */ + SecurityRequirement_t getWriteSecurityRequirement() const + { + return _valueAttribute.getWriteSecurityRequirement(); + } + + /** + * Set the security requirement of update operations. + * + * @note This security requirement is also applied to the write operation of + * the Client Characteristic Configuration Descriptor. + * + * @param[in] security The security requirement that must be met to send + * updates and accept write of the CCCD. + */ + void setUpdateSecurityRequirement(SecurityRequirement_t security) + { + _update_security = security.value(); + } + + /** + * Get the security requirement of update operations. + * + * @note This security requirement is also applied to the write operation of + * the Client Characteristic Configuration Descriptor. + * + * @return The security requirement that must be met to send updates and + * accept write of the CCCD. + */ + SecurityRequirement_t getUpdateSecurityRequirement() const + { + return static_cast(_update_security); } public: @@ -1561,10 +1733,54 @@ public: * Get the characteristic's required security. * * @return The characteristic's required security. + * + * @deprecated Fine grained security check has been added to with mbed OS + * 5.9. It is possible to set independently security requirements for read, + * write and update operations. In the meantime SecurityManager::SecurityMode_t + * is not used anymore to represent security requirements as it maps + * incorrectly the Bluetooth standard. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "Use getWriteSecurityRequirements, getReadSecurityRequirements and " + "getUpdateSecurityRequirements" + ) SecurityManager::SecurityMode_t getRequiredSecurity() const { - return _requiredSecurity; + SecurityRequirement_t max_sec = std::max( + std::max( + getReadSecurityRequirement(), + getWriteSecurityRequirement() + ), + getUpdateSecurityRequirement() + ); + + bool needs_signing = + _properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; + + switch(max_sec.value()) { + case SecurityRequirement_t::NONE: + MBED_ASSERT(needs_signing == false); + return SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; + + case SecurityRequirement_t::UNAUTHENTICATED: + return (needs_signing) ? + SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : + SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; + + case SecurityRequirement_t::AUTHENTICATED: + return (needs_signing) ? + SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : + SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; + + case SecurityRequirement_t::SC_AUTHENTICATED: + MBED_ASSERT(needs_signing == false); + // fallback to encryption with MITM + return SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; + default: + MBED_ASSERT(false); + return SecurityManager::SECURITY_MODE_NO_ACCESS; + } } /** @@ -1621,6 +1837,39 @@ public: } private: + + /** + * Loosely convert a SecurityManager::SecurityMode_t into a + * SecurityRequirement_t. + * + * @param[in] mode The security mode to convert + * + * @return The security requirement equivalent to the security mode in input. + */ + SecurityRequirement_t SecurityModeToAttSecurity( + SecurityManager::SecurityMode_t mode + ) { + switch(mode) { + case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: + case SecurityManager::SECURITY_MODE_NO_ACCESS: + // assuming access is managed by property and orthogonal to + // security mode ... + return SecurityRequirement_t::NONE; + + case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: + case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: + return SecurityRequirement_t::UNAUTHENTICATED; + + case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: + case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: + return SecurityRequirement_t::AUTHENTICATED; + + default: + // should not happens; makes the compiler happy. + return SecurityRequirement_t::NONE; + } + } + /** * Attribute that contains the actual value of this characteristic. */ @@ -1632,11 +1881,6 @@ private: */ uint8_t _properties; - /** - * The characteristic's required security. - */ - SecurityManager::SecurityMode_t _requiredSecurity; - /** * The characteristic's descriptor attributes. */ @@ -1669,6 +1913,14 @@ private: FunctionPointerWithContext writeAuthorizationCallback; + /** + * Security requirements of update operations. + * + * The peer must meet the security requirement to enable, disable and + * receive updates + */ + uint8_t _update_security: SecurityRequirement_t::size; + private: /* Disallow copy and assignment. */ GattCharacteristic(const GattCharacteristic &); From db565d38b3a63f3ccc72706978d29fe15796cda1 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 26 Apr 2018 19:00:43 +0100 Subject: [PATCH 130/274] BLE: remove useless flags in GattCharacteristic. --- features/FEATURE_BLE/ble/GattCharacteristic.h | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 4dab87184a..526e0fad39 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -1408,8 +1408,6 @@ public: _properties(props), _descriptors(descriptors), _descriptorCount(numDescriptors), - enabledReadAuthorization(false), - enabledWriteAuthorization(false), readAuthorizationCallback(), writeAuthorizationCallback(), _update_security(SecurityRequirement_t::NONE) { @@ -1560,7 +1558,6 @@ public: void (*callback)(GattWriteAuthCallbackParams *) ) { writeAuthorizationCallback.attach(callback); - enabledWriteAuthorization = true; } /** @@ -1581,7 +1578,6 @@ public: void (T::*member)(GattWriteAuthCallbackParams *) ) { writeAuthorizationCallback.attach(object, member); - enabledWriteAuthorization = true; } /** @@ -1598,7 +1594,6 @@ public: void (*callback)(GattReadAuthCallbackParams *) ) { readAuthorizationCallback.attach(callback); - enabledReadAuthorization = true; } /** @@ -1620,7 +1615,6 @@ public: void (T::*member)(GattReadAuthCallbackParams *) ) { readAuthorizationCallback.attach(object, member); - enabledReadAuthorization = true; } /** @@ -1803,7 +1797,7 @@ public: */ bool isReadAuthorizationEnabled() const { - return enabledReadAuthorization; + return readAuthorizationCallback; } /** @@ -1816,7 +1810,7 @@ public: */ bool isWriteAuthorizationEnabled() const { - return enabledWriteAuthorization; + return writeAuthorizationCallback; } /** @@ -1891,16 +1885,6 @@ private: */ uint8_t _descriptorCount; - /** - * Whether read authorization is enabled. - */ - bool enabledReadAuthorization; - - /** - * Whether write authorization is enabled. - */ - bool enabledWriteAuthorization; - /** * The registered callback handler for read authorization reply. */ From 80941af0f6c20d06bf982233d294fb08f6218c4f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:16:41 +0100 Subject: [PATCH 131/274] BLE: Add : LESC authenticated encryption to the list of possible link encryption. --- features/FEATURE_BLE/ble/BLETypes.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index b6fc3d5c9a..7dd3729a88 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -129,7 +129,8 @@ struct link_encryption_t : SafeEnum { NOT_ENCRYPTED, /**< The link is not secured. */ ENCRYPTION_IN_PROGRESS, /**< Link security is being established. */ ENCRYPTED, /**< The link is secure. */ - ENCRYPTED_WITH_MITM /**< The link is secure and authenticated. */ + ENCRYPTED_WITH_MITM, /**< The link is secure and authenticated. */ + ENCRYPTED_WITH_SC_AND_MITM /**< The link is secure and authenticated with a secure connection key. */ }; /** From c4b78ada0e9678e02a2997e375d746a48b7291fa Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:17:47 +0100 Subject: [PATCH 132/274] BLE: Set default mac address to 00:00:00:00:00:00 Both mac addresses are invalid but the bluetooth specification prefers to use all 0 addresses to represent an invalid address. --- features/FEATURE_BLE/ble/BLETypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 7dd3729a88..d595299350 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -427,10 +427,10 @@ typedef uint32_t sign_count_t; */ struct address_t : public byte_array_t<6> { /** - * Create an invalid mac address, equal to FF:FF:FF:FF:FF:FF + * Create an invalid mac address, equal to 00:00:00:00:00:00 */ address_t() { - memset(_value, 0xFF, sizeof(_value)); + memset(_value, 0x00, sizeof(_value)); } /** From 1e277bad501eb19aa31e2469fefffd52c802a2f4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:24:44 +0100 Subject: [PATCH 133/274] BLE: Lookup for non identity addresses when a secure entry is opened. A peer may not share a valid IRK and identity address during pairing (in that case the identity address received is all zeros). When this happens, the entry must be retrieved by looking at the address used by the peer during the connection. --- features/FEATURE_BLE/ble/pal/MemorySecurityDB.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h index eb28867734..85fcf35945 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h @@ -276,8 +276,16 @@ public: for (size_t i = 0; i < MAX_ENTRIES; i++) { if (_entries[i].state == ENTRY_FREE) { continue; - } else if (peer_address == _entries[i].peer_identity.identity_address - && _entries[i].flags.peer_address_is_public == peer_address_public) { + } else if ( + peer_address == _entries[i].peer_identity.identity_address && + peer_address_public ==_entries[i].flags.peer_address_is_public + ) { + return &_entries[i]; + } else if ( + _entries[i].peer_identity.identity_address == address_t() && + peer_address == _entries[i].flags.peer_address && + peer_address_public == _entries[i].flags.peer_address_is_public + ) { return &_entries[i]; } } From 74bc21496199efa02a1598bfd52a60e4725ffb99 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:27:38 +0100 Subject: [PATCH 134/274] BLE - Security Manager PAL: Add a function to remove the peer csrk. If the the upper layer has registered a peer csrk on the pal security manager then it must remove it once the connection is closed. This API allows the upper layer to remove the peer csrk registered earlier. --- features/FEATURE_BLE/ble/pal/PalSecurityManager.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index 4f100a0588..23a9badabb 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -883,6 +883,8 @@ public: sign_count_t sign_counter ) = 0; + virtual ble_error_t remove_peer_csrk(connection_handle_t connection) = 0; + //////////////////////////////////////////////////////////////////////////// // Authentication // From 2924bb4c868f9d971c387e9b05396695ee676edc Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:29:45 +0100 Subject: [PATCH 135/274] Cordio PAL ATT Client: initialize the local sign counter to 0. --- .../FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 3d536aff52..3d2bf6470c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -30,7 +30,8 @@ namespace cordio { class CordioAttClient : public ::ble::pal::AttClient { public: - CordioAttClient() : ::ble::pal::AttClient() { } + CordioAttClient() : ::ble::pal::AttClient(), _local_sign_counter(0) { } + virtual ~CordioAttClient() { } /** From e4813f4fe9fbed95752c5f2655a63cb419aaa04c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:33:36 +0100 Subject: [PATCH 136/274] Cordio PAL Security Manager: Copy locally own IRK. The IRK needs to be stored somewhere as it is not copied inside the stack, the stack just keeps a reference to it. --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 1 + .../targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index d7a0a21cd9..850e50f3d0 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -326,6 +326,7 @@ private: passkey_num_t _default_passkey; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; + irk_t _irk; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index e121906101..538d39e23f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -264,7 +264,8 @@ ble_error_t CordioSecurityManager::set_ltk_not_found( ble_error_t CordioSecurityManager::set_irk(const irk_t& irk) { - DmSecSetLocalIrk(const_cast(irk.data())); + _irk = irk; + DmSecSetLocalIrk(_irk.data()); return BLE_ERROR_NONE; } From 2da6fa3947b92e88b49615b83503d199b059fc53 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:35:16 +0100 Subject: [PATCH 137/274] Cordio PAL security manager: Copy locally own CSRK The stack does not copy csrk when DmSecSetLocalCsrk is invoked; it just retains a pointer to it. Therefore a copy is kept inside the pal. --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 1 + .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 850e50f3d0..2840a87365 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -327,6 +327,7 @@ private: bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; irk_t _irk; + csrk_t _csrk; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 538d39e23f..994af9a621 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -273,8 +273,11 @@ ble_error_t CordioSecurityManager::set_csrk( const csrk_t& csrk, sign_count_t sign_counter ) { + _csrk = csrk; + DmSecSetLocalCsrk(_csrk.data()); + // extra set the sign counter used by the client CordioAttClient::get_client().set_sign_counter(sign_counter); - DmSecSetLocalCsrk(const_cast(csrk.data())); + return BLE_ERROR_NONE; } From e39bb4b92c911cc57f57d4ea714a2b21b456d5fb Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:38:30 +0100 Subject: [PATCH 138/274] BLE - GenericGattClient: Exploit ENCRYPTED_WITH_SC_AND_MITM encryption. IF link is encrypted, authenticated or authenticated with lesc then signed write must be transformed into regular write commands. --- features/FEATURE_BLE/source/generic/GenericGattClient.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index cbf61a9246..9e6fae41dd 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -1089,9 +1089,11 @@ ble_error_t GenericGattClient::write( ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); SecurityManager &sm = createBLEInstance()->getSecurityManager(); ble_error_t status = sm.getLinkEncryption(connection_handle, &encryption); - if (status == BLE_ERROR_NONE - || encryption == ble::link_encryption_t::ENCRYPTED - || encryption == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { + if (status == BLE_ERROR_NONE && + (encryption == link_encryption_t::ENCRYPTED || + encryption == link_encryption_t::ENCRYPTED_WITH_MITM || + encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) + ) { cmd = GattClient::GATT_OP_WRITE_CMD; } } From 2e3c7e8ab788fac43389703fb36a6848ac97e49e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:45:24 +0100 Subject: [PATCH 139/274] Generic Security Manager: Set LinkKey to false unconditionally. This key distribution flags is for dual mode devices; mbed does not support BR/EDR. --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index fb21dd2cf9..8d7ce98479 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -63,7 +63,8 @@ ble_error_t GenericSecurityManager::init( _default_authentication.set_secure_connections(secure_connections); _default_authentication.set_keypress_notification(true); - _default_key_distribution.set_link(secure_connections); + // FIXME: depends on BR/EDR support + _default_key_distribution.set_link(false); _default_key_distribution.set_signing(signing); if (signing) { From 9880db7543c6ff8d4e52f4553aeb85330a3d5339 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:48:22 +0100 Subject: [PATCH 140/274] Generic Security Manager: Improve formating --- .../source/generic/GenericSecurityManager.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 8d7ce98479..e0dac6d25c 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -135,7 +135,8 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio /* by default the initiator doesn't send any keys other then identity */ KeyDistribution initiator_distribution( - KeyDistribution::KEY_DISTRIBUTION_IDENTITY | _default_key_distribution.get_link() + KeyDistribution::KEY_DISTRIBUTION_IDENTITY | + _default_key_distribution.get_link() ); /* if requested the initiator may send all the default keys for later @@ -183,13 +184,18 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con if (_master_sends_keys) { initiator_distribution &= _default_key_distribution; } else { - initiator_distribution &= KeyDistribution(KeyDistribution::KEY_DISTRIBUTION_IDENTITY | KeyDistribution::KEY_DISTRIBUTION_LINK); + initiator_distribution &= KeyDistribution( + KeyDistribution::KEY_DISTRIBUTION_IDENTITY | + KeyDistribution::KEY_DISTRIBUTION_LINK + ); } /* signing has to be offered and enabled on the link */ if (master_signing) { initiator_distribution.set_signing( - cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing() + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() ); } @@ -200,7 +206,9 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con /* signing has to be requested and enabled on the link */ if (responder_distribution.get_signing()) { responder_distribution.set_signing( - cb->signing_override_default ? cb->signing_requested : _default_key_distribution.get_signing() + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() ); } @@ -733,7 +741,12 @@ void GenericSecurityManager::set_ltk_cb( if (cb) { if (entryKeys) { - _pal.set_ltk(cb->connection, entryKeys->ltk, cb->ltk_mitm_protected, cb->secure_connections_paired); + _pal.set_ltk( + cb->connection, + entryKeys->ltk, + cb->ltk_mitm_protected, + cb->secure_connections_paired + ); } else { _pal.set_ltk_not_found(cb->connection); } From 1ac95e105b3de3da0a0985de9cc2178799d39d8f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:50:59 +0100 Subject: [PATCH 141/274] ble - Generic Security Manager: set signing unconditionnal to role reversal. A peripheral can act as a GATT client whether it is in the peripheral role or the central role therefore it doesn't make sense to enable signing only if roles will be reversed latter. --- .../source/generic/GenericSecurityManager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index e0dac6d25c..f531b7d2b5 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -139,14 +139,16 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio _default_key_distribution.get_link() ); + initiator_distribution.set_signing( + cb->signing_override_default ? + cb->signing_requested : + _default_key_distribution.get_signing() + ); + /* if requested the initiator may send all the default keys for later * use when roles are changed */ if (_master_sends_keys) { initiator_distribution = _default_key_distribution; - /* override default if requested */ - if (cb->signing_override_default) { - initiator_distribution.set_signing(cb->signing_requested); - } } KeyDistribution responder_distribution(_default_key_distribution); From f90eacfd27436e76e2a8dada65a48617820cfff9 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:53:18 +0100 Subject: [PATCH 142/274] Generic Security Manager: remove peer csrk at disconnection --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index f531b7d2b5..321b77102a 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -875,6 +875,8 @@ void GenericSecurityManager::on_disconnected( return; } + _pal.remove_peer_csrk(connection); + _db.close_entry(cb->db_entry); release_control_block(cb); From 41a34424741411dd723abdae53162d3352a18f49 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:54:03 +0100 Subject: [PATCH 143/274] Generic Security Manager: Set ltk to stored when the peer ltk has been recveived. --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 321b77102a..0de5b88095 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -1185,6 +1185,7 @@ void GenericSecurityManager::on_secure_connections_ltk_generated( cb->ltk_mitm_protected = cb->mitm_performed; cb->secure_connections_paired = true; + cb->ltk_stored = true; _db.set_entry_peer_ltk(cb->db_entry, ltk); } @@ -1198,6 +1199,7 @@ void GenericSecurityManager::on_keys_distributed_ltk( return; } cb->ltk_mitm_protected = cb->mitm_performed; + cb->ltk_stored = true; _db.set_entry_peer_ltk(cb->db_entry, ltk); } From 55eb7033b21aa64b8d171c9e55322ca778ae8499 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 11:54:25 +0100 Subject: [PATCH 144/274] Generic Security Manager: Set csrk to stored when the peer csrk has been received. --- features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 0de5b88095..857377776d 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -1280,6 +1280,7 @@ void GenericSecurityManager::on_keys_distributed_csrk( } cb->csrk_mitm_protected = cb->mitm_performed; + cb->csrk_stored = true; _db.set_entry_peer_csrk(cb->db_entry, csrk); From 0f64b1c988a2c02bc73c758ca0cfb0024f8316e1 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 12:26:24 +0100 Subject: [PATCH 145/274] CordioGattServer: Global refactoring The registration process has been breaked down into several functions that register the service attribute, characteristic declaration attributes, characteristic value attributes and characteristic descriptors. Service registration now consider all characteristics permissions: read, write and update. Permissions are also considered when updates needs to be propagated to peers. Handling of user authorization is also a change introduced by this refactoring. --- .../targets/TARGET_CORDIO/CordioGattServer.h | 73 +- .../TARGET_CORDIO/source/CordioGattServer.cpp | 1136 ++++++++++++----- 2 files changed, 851 insertions(+), 358 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index 15a758f723..effe2a5bcc 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -25,8 +25,11 @@ #include "wsf_types.h" #include "att_api.h" +/*! Maximum count of characteristics that can be stored for authorisation purposes */ +#define MAX_CHARACTERISTIC_AUTHORIZATION_CNT 20 + /*! client characteristic configuration descriptors settings */ -#define MAX_CCC_CNT 20 +#define MAX_CCCD_CNT 20 namespace ble { namespace vendor { @@ -159,36 +162,74 @@ public: } private: - static void cccCback(attsCccEvt_t *pEvt); - static void attCback(attEvt_t *pEvt); - static uint8_t attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); - static uint8_t attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + static uint16_t compute_attributes_count(GattService& service); + + void insert_service_attribute( + GattService& service, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_characteristic( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + bool is_characteristic_valid(GattCharacteristic *characteristic); + + void insert_characteristic_declaration_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_characteristic_value_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + ble_error_t insert_descriptor( + GattCharacteristic *characteristic, + GattAttribute* descriptor, + attsAttr_t *&attribute_it, + bool& cccd_created + ); + + ble_error_t insert_cccd( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it + ); + + static void cccd_cb(attsCccEvt_t *pEvt); + static void att_cb(const attEvt_t *pEvt); + static uint8_t atts_read_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr); + static uint8_t atts_write_cb(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr); + static uint8_t atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle); void add_generic_access_service(); void add_generic_attribute_service(); void* alloc_block(size_t block_size); + GattCharacteristic* get_auth_char(uint16_t value_handle); + bool get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const; + bool has_cccd(GattAttribute::Handle_t char_handle) const; + bool is_update_authorized(Gap::Handle_t connection, GattAttribute::Handle_t value_handle); struct alloc_block_t { alloc_block_t* next; uint8_t data[1]; }; - struct internal_char_t { - uint16_t descLen; - }; - struct internal_service_t { - uint16_t uuidLen; - internal_char_t *chars; - attsGroup_t *attGroup; + attsGroup_t attGroup; internal_service_t *next; }; pal::SigningEventMonitor::EventHandler *_signing_event_handler; - attsCccSet_t cccSet[MAX_CCC_CNT]; - uint16_t cccValues[MAX_CCC_CNT]; - uint16_t cccHandles[MAX_CCC_CNT]; - uint8_t cccCnt; + attsCccSet_t cccds[MAX_CCCD_CNT]; + uint16_t cccd_values[MAX_CCCD_CNT]; + uint16_t cccd_handles[MAX_CCCD_CNT]; + uint8_t cccd_cnt; + + GattCharacteristic *_auth_char[MAX_CHARACTERISTIC_AUTHORIZATION_CNT]; + uint8_t _auth_char_count; struct { attsGroup_t service; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 91bba27650..0d6b73376d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -15,18 +15,47 @@ */ #include +#include "CordioBLE.h" #include "CordioGattServer.h" #include "mbed.h" #include "wsf_types.h" #include "att_api.h" -static UUID cccUUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); -static const uint16_t cccSize = sizeof(uint16_t); - namespace ble { namespace vendor { namespace cordio { +namespace { + +static UUID CCCD_UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG); +static const uint16_t CCCD_SIZE = sizeof(uint16_t); + +static const unsigned int READ_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ; +static const unsigned int WRITE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE; +static const unsigned int WRITE_WITHOUT_RESPONSE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE; +static const unsigned int SIGNED_WRITE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; +static const unsigned int NOTIFY_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY; +static const unsigned int INDICATE_PROPERTY = + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE; + +static const uint8_t WRITABLE_PROPERTIES = + WRITE_PROPERTY | + WRITE_WITHOUT_RESPONSE_PROPERTY | + SIGNED_WRITE_PROPERTY; + +static const uint8_t UPDATE_PROPERTIES = + NOTIFY_PROPERTY | + INDICATE_PROPERTY; + +static const uint16_t CONNECTION_ID_LIMIT = 0x100; + +} // end of anonymous namespace + GattServer &GattServer::getInstance() { static GattServer m_instance; @@ -35,384 +64,650 @@ GattServer &GattServer::getInstance() void GattServer::initialize() { + AttsAuthorRegister(atts_auth_cb); add_generic_access_service(); add_generic_attribute_service(); } ble_error_t GattServer::addService(GattService &service) { - ++currentHandle; - uint16_t startHandle = currentHandle; - - internal_service_t *internal_service = new internal_service_t; - - if (registered_service) { - internal_service->next = registered_service; - } else { - internal_service->next = NULL; - } - - registered_service = internal_service; - - // Create cordio attribute group - internal_service->attGroup = new attsGroup_t; + // create and fill the service structure + internal_service_t *att_service = new internal_service_t; + att_service->attGroup.pNext = NULL; + att_service->attGroup.readCback = atts_read_cb; + att_service->attGroup.writeCback = atts_write_cb; // Determine the attribute list length - unsigned int attListLen = 1; - for (int i = 0; i < service.getCharacteristicCount(); i++) { - attListLen += 2; - GattCharacteristic *p_char = service.getCharacteristic(i); - - attListLen += p_char->getDescriptorCount(); - if (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE)) { - // add a CCCD - attListLen++; - } - } + uint16_t attributes_count = compute_attributes_count(service); // Create cordio attribute list - internal_service->attGroup->pAttr = (attsAttr_t*)alloc_block(attListLen * sizeof(attsAttr_t)); - if (internal_service->attGroup->pAttr == NULL) { + att_service->attGroup.pAttr = + (attsAttr_t*) alloc_block(attributes_count * sizeof(attsAttr_t)); + if (att_service->attGroup.pAttr == NULL) { return BLE_ERROR_BUFFER_OVERFLOW; } - // Create characteristics - internal_service->chars = new internal_char_t [service.getCharacteristicCount()]; - - attsAttr_t *currAtt = internal_service->attGroup->pAttr; + // insert every element in the iterator + attsAttr_t *attribute_it = att_service->attGroup.pAttr; /* Service */ - currAtt->pUuid = attPrimSvcUuid; - if (service.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - internal_service->uuidLen = UUID::LENGTH_OF_LONG_UUID; - } else { - internal_service->uuidLen = sizeof(UUID::ShortUUIDBytes_t); - } - currAtt->pValue = (uint8_t*)alloc_block(internal_service->uuidLen); - memcpy(currAtt->pValue, service.getUUID().getBaseUUID(), internal_service->uuidLen); - currAtt->maxLen = internal_service->uuidLen; - currAtt->pLen = &internal_service->uuidLen; - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ; - - currAtt++; + insert_service_attribute(service, attribute_it); + att_service->attGroup.startHandle = currentHandle; + service.setHandle(currentHandle); /* Add characteristics to the service */ for (int i = 0; i < service.getCharacteristicCount(); i++) { + ble_error_t err = insert_characteristic( + service.getCharacteristic(i), + attribute_it + ); + if (err) { + // FIXME: proper cleanup of data structure: + // - att_service->attGroup.pAttr + // - blocks allocated for characteristics value + // NOTE: those are rightfully released when reset() is called. + delete att_service; + return err; + } + } + att_service->attGroup.endHandle = currentHandle; + + // add the service to the list of registered services + if (registered_service) { + att_service->next = registered_service; + } else { + att_service->next = NULL; + } + + registered_service = att_service; + + // register services and update cccds + AttsAddGroup(&att_service->attGroup); + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); + return BLE_ERROR_NONE; +} + +uint16_t GattServer::compute_attributes_count(GattService& service) +{ + // start at 1, one attribute is required for the service itself + uint16_t attributes_count = 1; + for (int i = 0; i < service.getCharacteristicCount(); i++) { + attributes_count += 2; GattCharacteristic *p_char = service.getCharacteristic(i); + attributes_count += p_char->getDescriptorCount(); + if (p_char->getProperties() & UPDATE_PROPERTIES) { + // add a CCCD + ++attributes_count; - /* Skip any incompletely defined, read-only characteristics. */ - if ((p_char->getValueAttribute().getValuePtr() == NULL) && - (p_char->getValueAttribute().getLength() == 0) && - (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { - continue; - } - - // Create Characteristic Attribute - currentHandle += 2; - currAtt->pUuid = attChUuid; - - p_char->getValueAttribute().setHandle(currentHandle); - internal_service->chars[i].descLen = 1 + sizeof(currentHandle) + p_char->getValueAttribute().getUUID().getLen(); - currAtt->pValue = (uint8_t*) alloc_block(internal_service->chars[i].descLen); - uint8_t *pValue = currAtt->pValue; - *pValue++ = p_char->getProperties(); - memcpy(pValue, ¤tHandle, sizeof(currentHandle)); - pValue += sizeof(currentHandle); - memcpy(pValue, p_char->getValueAttribute().getUUID().getBaseUUID(), p_char->getValueAttribute().getUUID().getLen()); - - currAtt->pLen = &internal_service->chars[i].descLen; - currAtt->maxLen = internal_service->chars[i].descLen; - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ; - currAtt++; - - // Create Value Attribute - currAtt->pUuid = p_char->getValueAttribute().getUUID().getBaseUUID(); - currAtt->maxLen = p_char->getValueAttribute().getMaxLength(); - currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); - *currAtt->pLen = p_char->getValueAttribute().getLength(); - currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); - memcpy(currAtt->pValue, p_char->getValueAttribute().getValuePtr(), *currAtt->pLen); - memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); - - currAtt->settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK; - if (p_char->getValueAttribute().getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - currAtt->settings |= ATTS_SET_UUID_128; - } - if (p_char->getValueAttribute().hasVariableLength()) { - currAtt->settings |= ATTS_SET_VARIABLE_LEN; - } - - currAtt->permissions = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ) { currAtt->permissions |= ATTS_PERMIT_READ; } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE) { currAtt->permissions |= ATTS_PERMIT_WRITE; } - currAtt++; - - bool cccCreated = false; - - for (int i = 0; i < p_char->getDescriptorCount(); i++) { - GattAttribute *p_att = p_char->getDescriptor(i); - - currentHandle++; - - p_att->setHandle(currentHandle); - - currAtt->pUuid = p_att->getUUID().getBaseUUID(); - currAtt->maxLen = p_att->getMaxLength(); - currAtt->pLen = (uint16_t*) alloc_block(currAtt->maxLen + sizeof(uint16_t)); - *currAtt->pLen = p_att->getLength(); - currAtt->pValue = (uint8_t*) ((uint16_t*)currAtt->pLen + 1); - memcpy(currAtt->pValue, p_att->getValuePtr(), *currAtt->pLen); - memset(currAtt->pValue + *currAtt->pLen, 0, currAtt->maxLen - *currAtt->pLen); - - currAtt->settings = 0; - currAtt->permissions = ATTS_PERMIT_READ | ATTS_PERMIT_WRITE; - if (p_att->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { - currAtt->settings |= ATTS_SET_UUID_128; - } - if (p_att->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { - cccCreated = true; - currAtt->settings |= ATTS_SET_CCC; - currAtt->permissions |= ATTS_PERMIT_READ; - currAtt->permissions |= ATTS_PERMIT_WRITE; - - if (cccCnt < MAX_CCC_CNT) { - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; - } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; - } - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); - cccCnt++; - } else { - return BLE_ERROR_PARAM_OUT_OF_RANGE; + // verify that it hasn't been counted twice + for (size_t j = 0; j < p_char->getDescriptorCount(); ++j) { + if (p_char->getDescriptor(j)->getUUID() == + UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) + ) { + --attributes_count; + break; } } - if (p_att->hasVariableLength()) { - currAtt->settings |= ATTS_SET_VARIABLE_LEN; - } - currAtt++; - } - - if (!cccCreated && (p_char->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE))) { - /* There was not a CCCD included in the descriptors, but this - * characteristic is notifiable and/or indicatable. A CCCD is - * required so create one now. - */ - if (cccCnt >= MAX_CCC_CNT) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - currentHandle++; - - currAtt->pUuid = cccUUID.getBaseUUID(); - currAtt->pValue = (uint8_t*)&cccValues[cccCnt]; - currAtt->pLen = (uint16_t*)&cccSize; - currAtt->maxLen = sizeof(uint16_t); - currAtt->settings = ATTS_SET_CCC; - currAtt->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); - - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = 0; - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; - } - if (p_char->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) { - cccSet[cccCnt].valueRange |= ATT_CLIENT_CFG_INDICATE; - } - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = p_char->getValueAttribute().getHandle(); - - cccCnt++; - currAtt++; } } - internal_service->attGroup->pNext = NULL; - internal_service->attGroup->readCback = attsReadCback; - internal_service->attGroup->writeCback = attsWriteCback; - internal_service->attGroup->startHandle = startHandle; - internal_service->attGroup->endHandle = currentHandle; - AttsAddGroup(internal_service->attGroup); - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + return attributes_count; +} - service.setHandle(startHandle); +void GattServer::insert_service_attribute( + GattService& service, + attsAttr_t *&attribute_it +) { + ++currentHandle; + const UUID& service_uuid = service.getUUID(); + + attribute_it->pUuid = attPrimSvcUuid; + if (service_uuid.shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->maxLen = UUID::LENGTH_OF_LONG_UUID; + } else { + attribute_it->maxLen = sizeof(UUID::ShortUUIDBytes_t); + } + attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen); + memcpy(attribute_it->pValue, service_uuid.getBaseUUID(), attribute_it->maxLen); + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->settings = 0; + attribute_it->permissions = ATTS_PERMIT_READ; + + ++attribute_it; +} + +ble_error_t GattServer::insert_characteristic( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + bool valid = is_characteristic_valid(characteristic); + if (!valid) { + return BLE_ERROR_INVALID_PARAM; + } + + uint8_t properties = characteristic->getProperties(); + + // Create Characteristic Declaration Attribute + insert_characteristic_declaration_attribute(characteristic, attribute_it); + insert_characteristic_value_attribute(characteristic, attribute_it); + + // insert descriptors + bool cccd_created = false; + for (size_t i = 0; i < characteristic->getDescriptorCount(); i++) { + insert_descriptor( + characteristic, + characteristic->getDescriptor(i), + attribute_it, + cccd_created + ); + } + + // insert implicit CCCD + if ((properties & UPDATE_PROPERTIES) && (cccd_created == false)) { + insert_cccd(characteristic, attribute_it); + } return BLE_ERROR_NONE; } -ble_error_t GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t * lengthP) -{ - uint16_t attribute_length = 0; - uint8_t* attribute_value = NULL; +bool GattServer::is_characteristic_valid(GattCharacteristic *characteristic) { + uint8_t properties = characteristic->getProperties(); - if (AttsGetAttr(attributeHandle, &attribute_length, &attribute_value) != ATT_SUCCESS) { + // nothing to read while the characteristic is flagged as readable + if ((characteristic->getValueAttribute().getValuePtr() == NULL) && + (characteristic->getValueAttribute().getMaxLength() == 0) && + (properties == READ_PROPERTY) && + (characteristic->isReadAuthorizationEnabled() == false) + ) { + return false; + } + + // nothing to write while the characteristic is flagged as writable + if ((characteristic->getValueAttribute().getValuePtr() == NULL) && + (characteristic->getValueAttribute().getMaxLength() == 0) && + (properties & WRITABLE_PROPERTIES) && + (characteristic->isWriteAuthorizationEnabled() == false) + ) { + return false; + } + + // check for invalid permissions + if ((properties == SIGNED_WRITE_PROPERTY) && + (characteristic->getWriteSecurityRequirement() == att_security_requirement_t::NONE || + characteristic->getWriteSecurityRequirement() == att_security_requirement_t::SC_AUTHENTICATED) + ) { + return false; + } + + return true; +} + +void GattServer::insert_characteristic_declaration_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + const UUID& value_uuid = characteristic->getValueAttribute().getUUID(); + + // move the current handle to point to the value handle + currentHandle += 2; + characteristic->getValueAttribute().setHandle(currentHandle); + + // fill the cordio attribute + attribute_it->pUuid = attChUuid; + attribute_it->maxLen = 1 + sizeof(currentHandle) + value_uuid.getLen(); + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->pValue = (uint8_t*) alloc_block(attribute_it->maxLen); + attribute_it->settings = 0; + attribute_it->permissions = ATTS_PERMIT_READ; + + // set the attribute value + uint8_t *value_it = attribute_it->pValue; + *value_it++ = characteristic->getProperties(); + memcpy(value_it, ¤tHandle, sizeof(currentHandle)); + value_it += sizeof(currentHandle); + memcpy(value_it, value_uuid.getBaseUUID(), value_uuid.getLen()); + + ++attribute_it; +} + +ble_error_t GattServer::insert_characteristic_value_attribute( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + GattAttribute &value_attribute = characteristic->getValueAttribute(); + uint8_t properties = characteristic->getProperties(); + + // note: currentHandle has been already moved to the correct value + + // Create Value Attribute + attribute_it->pUuid = value_attribute.getUUID().getBaseUUID(); + attribute_it->maxLen = characteristic->getValueAttribute().getMaxLength(); + attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t)); + *attribute_it->pLen = value_attribute.getLength(); + attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1); + memcpy(attribute_it->pValue, value_attribute.getValuePtr(), *attribute_it->pLen); + memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen); + + // Set value attribute settings + if (properties & READ_PROPERTY) { + attribute_it->settings = ATTS_SET_READ_CBACK; + } + if (properties & WRITABLE_PROPERTIES) { + attribute_it->settings = ATTS_SET_WRITE_CBACK; + } + if (value_attribute.getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->settings |= ATTS_SET_UUID_128; + } + if (value_attribute.hasVariableLength()) { + attribute_it->settings |= ATTS_SET_VARIABLE_LEN; + } + if (properties & SIGNED_WRITE_PROPERTY) { + attribute_it->settings |= ATTS_SET_ALLOW_SIGNED; + } + + // setup permissions + attribute_it->permissions = 0; + + // configure read permission + if (properties & READ_PROPERTY) { + attribute_it->permissions |= ATTS_PERMIT_READ; + switch (characteristic->getReadSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_READ_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH | + ATTS_PERMIT_READ_AUTHORIZ; + break; + } + } + + // configure write permission + if (properties & WRITABLE_PROPERTIES) { + attribute_it->permissions |= ATTS_PERMIT_WRITE; + switch (characteristic->getWriteSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH | + ATTS_PERMIT_WRITE_AUTHORIZ; + break; + } + } + + // Register characteristic in authorisation list + // Note: ATTS_PERMIT_*_AUTHORIZ is uniquely used to check if security + // requirements are met according to the security requirements set in the + // characteristic. + // User defined security authorisation does not impact this flag + if ((attribute_it->permissions & (ATTS_PERMIT_READ_AUTHORIZ | ATTS_PERMIT_WRITE_AUTHORIZ)) || + (attribute_it->permissions & UPDATE_PROPERTIES) || + characteristic->isReadAuthorizationEnabled() || + characteristic->isWriteAuthorizationEnabled() + ) { + if ( _auth_char_count >= MAX_CHARACTERISTIC_AUTHORIZATION_CNT) { + return BLE_ERROR_NO_MEM; + } + _auth_char[_auth_char_count] = characteristic; + ++_auth_char_count; + } + + ++attribute_it; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::insert_descriptor( + GattCharacteristic *characteristic, + GattAttribute* descriptor, + attsAttr_t *&attribute_it, + bool& cccd_created +) { + uint8_t properties = characteristic->getProperties(); + + currentHandle++; + + descriptor->setHandle(currentHandle); + + attribute_it->pUuid = descriptor->getUUID().getBaseUUID(); + attribute_it->maxLen = descriptor->getMaxLength(); + attribute_it->pLen = (uint16_t*) alloc_block(attribute_it->maxLen + sizeof(uint16_t)); + *attribute_it->pLen = descriptor->getLength(); + attribute_it->pValue = (uint8_t*) ((uint16_t*)attribute_it->pLen + 1); + memcpy(attribute_it->pValue, descriptor->getValuePtr(), *attribute_it->pLen); + memset(attribute_it->pValue + *attribute_it->pLen, 0, attribute_it->maxLen - *attribute_it->pLen); + + attribute_it->settings = 0; + + if (descriptor->getUUID().shortOrLong() == UUID::UUID_TYPE_LONG) { + attribute_it->settings |= ATTS_SET_UUID_128; + } + + // handle the special case of a CCCD + if (descriptor->getUUID() == UUID(BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)) { + if (cccd_cnt >= MAX_CCCD_CNT) { + return BLE_ERROR_NO_MEM; + } + + if (descriptor->isReadAllowed() == false || + descriptor->getReadSecurityRequirement() != att_security_requirement_t::NONE + ) { + return BLE_ERROR_INVALID_PARAM; + } + + cccd_created = true; + attribute_it->settings |= ATTS_SET_CCC; + + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = 0; + if (properties & NOTIFY_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (properties & INDICATE_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle(); + cccd_cnt++; + } + + if (descriptor->hasVariableLength()) { + attribute_it->settings |= ATTS_SET_VARIABLE_LEN; + } + + // setup permissions + attribute_it->permissions = 0; + + // configure read permission + if (descriptor->isReadAllowed()) { + attribute_it->permissions |= ATTS_PERMIT_READ; + switch (descriptor->getReadSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_READ_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_READ_ENC | + ATTS_PERMIT_READ_AUTH | + ATTS_PERMIT_READ_AUTHORIZ; + break; + } + } + + // configure write permission + if (descriptor->isReadAllowed()) { + attribute_it->permissions |= ATTS_PERMIT_WRITE; + switch (descriptor->getWriteSecurityRequirement().value()) { + case att_security_requirement_t::NONE: + break; + case att_security_requirement_t::UNAUTHENTICATED: + attribute_it->permissions |= ATTS_PERMIT_WRITE_ENC; + break; + case att_security_requirement_t::AUTHENTICATED: + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH; + break; + case att_security_requirement_t::SC_AUTHENTICATED: + // Note: check done in the cordio stack doesn't cover LESC + // so this one is done in attsAuthorCback + attribute_it->permissions |= + ATTS_PERMIT_WRITE_ENC | + ATTS_PERMIT_WRITE_AUTH | + ATTS_PERMIT_WRITE_AUTHORIZ; + break; + } + } + + attribute_it++; + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::insert_cccd( + GattCharacteristic *characteristic, + attsAttr_t *&attribute_it +) { + if (cccd_cnt >= MAX_CCCD_CNT) { + return BLE_ERROR_NO_MEM; + } + + uint8_t properties = characteristic->getProperties(); + + currentHandle++; + + attribute_it->pUuid = CCCD_UUID.getBaseUUID(); + attribute_it->pValue = (uint8_t*) &cccd_values[cccd_cnt]; + attribute_it->maxLen = CCCD_SIZE; + attribute_it->pLen = &attribute_it->maxLen; + attribute_it->settings = ATTS_SET_CCC; + attribute_it->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); + + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = 0; + if (properties & NOTIFY_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_NOTIFY; + } + if (properties & INDICATE_PROPERTY) { + cccds[cccd_cnt].valueRange |= ATT_CLIENT_CFG_INDICATE; + } + cccds[cccd_cnt].secLevel = characteristic->getUpdateSecurityRequirement().value(); + cccd_handles[cccd_cnt] = characteristic->getValueAttribute().getHandle(); + + cccd_cnt++; + attribute_it++; + + return BLE_ERROR_NONE; +} + +ble_error_t GattServer::read( + GattAttribute::Handle_t att_handle, + uint8_t buffer[], + uint16_t * buffer_length +) { + uint16_t att_length = 0; + uint8_t* att_value = NULL; + + if (AttsGetAttr(att_handle, &att_length, &att_value) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } if (buffer) { - memcpy(buffer, attribute_value, std::min(*lengthP, attribute_length)); + memcpy(buffer, att_value, std::min(*buffer_length, att_length)); } - *lengthP = attribute_length; + *buffer_length = att_length; return BLE_ERROR_NONE; } -ble_error_t GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) -{ +ble_error_t GattServer::read( + Gap::Handle_t connection, + GattAttribute::Handle_t att_handle, + uint8_t buffer[], + uint16_t *buffer_length +) { // Check to see if this is a CCCD - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - if (connectionHandle == DM_CONN_ID_NONE) { // CCCDs are always 16 bits - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - *((uint16_t*)buffer) = AttsCccGet(connectionHandle, idx); - *lengthP = 2; // CCCDs are always 16 bits - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if (connection == DM_CONN_ID_NONE) { + return BLE_ERROR_PARAM_OUT_OF_RANGE; } + uint16_t cccd_value = AttsCccGet(connection, cccd_index); + uint16_t cccd_length = sizeof(cccd_value); + + if (buffer) { + memcpy(buffer, &cccd_value, std::min(*buffer_length, cccd_length)); + } + + *buffer_length = cccd_length; + return BLE_ERROR_NONE; } // This is not a CCCD. Use the non-connection specific update method. - return read(attributeHandle, buffer, lengthP); + return read(att_handle, buffer, buffer_length); } -ble_error_t GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ +ble_error_t GattServer::write( + GattAttribute::Handle_t att_handle, + const uint8_t buffer[], + uint16_t len, + bool local_only +) { // Check to see if this is a CCCD, if it is the case update the value for all // connections - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { - if (DmConnInUse(conn_id) == true) { - ++conn_found; - } else { - continue; - } - - AttsCccSet(conn_id, idx, *((uint16_t*)buffer)); - } - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if (len != sizeof(uint16_t)) { + return BLE_ERROR_INVALID_PARAM; } + + uint16_t cccd_value; + memcpy(&cccd_value, buffer, sizeof(cccd_value)); + + uint16_t conn_id = 0; + uint16_t conn_found = 0; + while ((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { + if (DmConnInUse(conn_id) == true) { + ++conn_found; + AttsCccSet(conn_id, cccd_index, cccd_value); + } + ++conn_id; + } + + return BLE_ERROR_NONE; } // write the value to the attribute handle - if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } // return if the update does not have to be propagated to peers - if (localOnly) { + if (local_only || !has_cccd(att_handle)) { return BLE_ERROR_NONE; } - // Check to see if this characteristic has a CCCD attribute - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccHandles[idx]) { - break; - } - } - - // exit if the characteristic has no CCCD attribute - if (idx >= cccCnt) { - return BLE_ERROR_NONE; - } - - // This characteristic has a CCCD attribute. Handle notifications and indications. - // for all connections - - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { + // This characteristic has a CCCD attribute. Handle notifications and + // indications for all active connections if the authentication is + // successful + uint16_t conn_id = 0; + uint16_t conn_found = 0; + while((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { if (DmConnInUse(conn_id) == true) { ++conn_found; - } else { - uint16_t cccEnabled = AttsCccEnabled(conn_id, idx); - if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { - AttsHandleValueNtf(conn_id, attributeHandle, len, (uint8_t*)buffer); - } - if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { - AttsHandleValueInd(conn_id, attributeHandle, len, (uint8_t*)buffer); + if (is_update_authorized(conn_id, att_handle)) { + uint16_t cccd_config = AttsCccEnabled(conn_id, cccd_index); + if (cccd_config & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(conn_id, att_handle, len, (uint8_t*)buffer); + } + if (cccd_config & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(conn_id, att_handle, len, (uint8_t*)buffer); + } } } - - AttsCccSet(conn_id, idx, *((uint16_t*)buffer)); + ++conn_id; } return BLE_ERROR_NONE; } -ble_error_t GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) -{ +ble_error_t GattServer::write( + Gap::Handle_t connection, + GattAttribute::Handle_t att_handle, + const uint8_t buffer[], + uint16_t len, + bool local_only +) { // Check to see if this is a CCCD - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccSet[idx].handle) { - if ((connectionHandle == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - AttsCccSet(connectionHandle, idx, *((uint16_t*)buffer)); - return BLE_ERROR_NONE; + uint8_t cccd_index; + if (get_cccd_id(att_handle, cccd_index)) { + if ((connection == DM_CONN_ID_NONE) || (len != 2)) { // CCCDs are always 16 bits + return BLE_ERROR_PARAM_OUT_OF_RANGE; } + + uint16_t cccd_value; + memcpy(&cccd_value, buffer, sizeof(cccd_value)); + AttsCccSet(connection, cccd_index, cccd_value); + return BLE_ERROR_NONE; } // write the value to the attribute handle - if (AttsSetAttr(attributeHandle, len, (uint8_t*)buffer) != ATT_SUCCESS) { + if (AttsSetAttr(att_handle, len, (uint8_t*)buffer) != ATT_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } // return if the update does not have to be propagated to peers - if (localOnly) { - return BLE_ERROR_NONE; - } - - // Check to see if this characteristic has a CCCD attribute - for (idx = 0; idx < cccCnt; idx++) { - if (attributeHandle == cccHandles[idx]) { - break; - } - } - - // exit if the characteristic has no CCCD attribute - if (idx >= cccCnt) { + if (local_only || !has_cccd(att_handle)) { return BLE_ERROR_NONE; } // This characteristic has a CCCD attribute. Handle notifications and indications. - uint16_t cccEnabled = AttsCccEnabled(connectionHandle, idx); - if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { - AttsHandleValueNtf(connectionHandle, attributeHandle, len, (uint8_t*)buffer); - } - if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { - AttsHandleValueInd(connectionHandle, attributeHandle, len, (uint8_t*)buffer); + if (is_update_authorized(connection, att_handle)) { + uint16_t cccEnabled = AttsCccEnabled(connection, cccd_index); + if (cccEnabled & ATT_CLIENT_CFG_NOTIFY) { + AttsHandleValueNtf(connection, att_handle, len, (uint8_t*)buffer); + } + if (cccEnabled & ATT_CLIENT_CFG_INDICATE) { + AttsHandleValueInd(connection, att_handle, len, (uint8_t*)buffer); + } } return BLE_ERROR_NONE; } -ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) -{ - for (size_t idx = 0; idx < cccCnt; idx++) { - if (characteristic.getValueHandle() == cccHandles[idx]) { - for (uint16_t conn_id = 0, conn_found = 0; (conn_found < DM_CONN_MAX) && (conn_id < 0x100); ++conn_id) { +ble_error_t GattServer::areUpdatesEnabled( + const GattCharacteristic &characteristic, + bool *enabled +) { + for (size_t idx = 0; idx < cccd_cnt; idx++) { + if (characteristic.getValueHandle() == cccd_handles[idx]) { + uint16_t conn_id = 0; + uint16_t conn_found = 0; + + while ((conn_found < DM_CONN_MAX) && (conn_id < CONNECTION_ID_LIMIT)) { if (DmConnInUse(conn_id) == true) { ++conn_found; - } else { - continue; - } + uint16_t cccd_value = AttsCccGet(conn_id, idx); + if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + *enabled = true; + return BLE_ERROR_NONE; + } - uint16_t cccValue = AttsCccGet(conn_id, idx); - if ((cccValue & ATT_CLIENT_CFG_NOTIFY) || (cccValue & ATT_CLIENT_CFG_INDICATE)) { - *enabledP = true; - return BLE_ERROR_NONE; } + ++conn_id; } - *enabledP = false; + *enabled = false; return BLE_ERROR_NONE; } } @@ -420,23 +715,26 @@ ble_error_t GattServer::areUpdatesEnabled(const GattCharacteristic &characterist return BLE_ERROR_PARAM_OUT_OF_RANGE; } -ble_error_t GattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) -{ - if (connectionHandle != DM_CONN_ID_NONE) { - uint8_t idx; - for (idx = 0; idx < cccCnt; idx++) { - if (characteristic.getValueHandle() == cccHandles[idx]) { - uint16_t cccValue = AttsCccGet(connectionHandle, idx); - if (cccValue & ATT_CLIENT_CFG_NOTIFY || (cccValue & ATT_CLIENT_CFG_INDICATE)) { - *enabledP = true; - } else { - *enabledP = false; - } - return BLE_ERROR_NONE; - } - } +ble_error_t GattServer::areUpdatesEnabled( + Gap::Handle_t connectionHandle, + const GattCharacteristic &characteristic, + bool *enabled +) { + if (connectionHandle == DM_CONN_ID_NONE) { + return BLE_ERROR_INVALID_PARAM; } + for (uint8_t idx = 0; idx < cccd_cnt; idx++) { + if (characteristic.getValueHandle() == cccd_handles[idx]) { + uint16_t cccd_value = AttsCccGet(connectionHandle, idx); + if (cccd_value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { + *enabled = true; + } else { + *enabled = false; + } + return BLE_ERROR_NONE; + } + } return BLE_ERROR_PARAM_OUT_OF_RANGE; } @@ -511,9 +809,7 @@ ble_error_t GattServer::reset(void) while (registered_service) { internal_service_t* s = registered_service; registered_service = s->next; - AttsRemoveGroup(s->attGroup->startHandle); - delete s->attGroup; - delete[] s->chars; + AttsRemoveGroup(s->attGroup.startHandle); delete s; } @@ -528,33 +824,60 @@ ble_error_t GattServer::reset(void) free(generic_access_service.device_name_value()); currentHandle = 0; - cccCnt = 0; + cccd_cnt = 0; - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + _auth_char_count = 0; + + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); return BLE_ERROR_NONE; } -void GattServer::cccCback(attsCccEvt_t *pEvt) +void GattServer::cccd_cb(attsCccEvt_t *evt) { - if (pEvt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE)) { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_ENABLED, pEvt->handle); - } else { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_UPDATES_DISABLED, pEvt->handle); + GattServerEvents::gattEvent_t evt_type = + evt->value & (ATT_CLIENT_CFG_NOTIFY | ATT_CLIENT_CFG_INDICATE) ? + GattServerEvents::GATT_EVENT_UPDATES_ENABLED : + GattServerEvents::GATT_EVENT_UPDATES_DISABLED; + + getInstance().handleEvent(evt_type, evt->handle); +} + +void GattServer::att_cb(const attEvt_t *evt) +{ + if (evt->hdr.status == ATT_SUCCESS && evt->hdr.event == ATTS_HANDLE_VALUE_CNF) { + getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, evt->handle); } } -void GattServer::attCback(attEvt_t *pEvt) -{ - // TODO enable again - if (pEvt->hdr.status == ATT_SUCCESS) { - getInstance().handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT, pEvt->handle); - } -} +uint8_t GattServer::atts_read_cb( + dmConnId_t connId, + uint16_t handle, + uint8_t operation, + uint16_t offset, + attsAttr_t *pAttr +) { + GattCharacteristic* auth_char = getInstance().get_auth_char(handle); + if (auth_char && auth_char->isReadAuthorizationEnabled()) { + GattReadAuthCallbackParams read_auth_params = { + connId, + handle, + offset, + /* len */ 0, + /* data */ NULL, + AUTH_CALLBACK_REPLY_SUCCESS + }; -uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, attsAttr_t *pAttr) -{ - GattReadCallbackParams cbParams = { + GattAuthCallbackReply_t ret = auth_char->authorizeRead(&read_auth_params); + if (ret != AUTH_CALLBACK_REPLY_SUCCESS) { + return ret & 0xFF; + } + + pAttr->pValue = read_auth_params.data; + *pAttr->pLen = read_auth_params.len; + } + + GattReadCallbackParams read_params = { connId, handle, offset, @@ -562,13 +885,20 @@ uint8_t GattServer::attsReadCback(dmConnId_t connId, uint16_t handle, uint8_t op pAttr->pValue, /* status */ BLE_ERROR_NONE, }; - getInstance().handleDataReadEvent(&cbParams); + getInstance().handleDataReadEvent(&read_params); return ATT_SUCCESS; } -uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len, uint8_t *pValue, attsAttr_t *pAttr) -{ +uint8_t GattServer::atts_write_cb( + dmConnId_t connId, + uint16_t handle, + uint8_t operation, + uint16_t offset, + uint16_t len, + uint8_t *pValue, + attsAttr_t *pAttr +) { uint8_t err; /* TODO: offset is not handled properly */ @@ -604,7 +934,24 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o break; } - GattWriteCallbackParams cbParams = { + GattCharacteristic* auth_char = getInstance().get_auth_char(handle); + if (auth_char && auth_char->isWriteAuthorizationEnabled()) { + GattWriteAuthCallbackParams write_auth_params = { + connId, + handle, + offset, + len, + pValue, + AUTH_CALLBACK_REPLY_SUCCESS + }; + + GattAuthCallbackReply_t ret = auth_char->authorizeWrite(&write_auth_params); + if (ret!= AUTH_CALLBACK_REPLY_SUCCESS) { + return ret & 0xFF; + } + } + + GattWriteCallbackParams write_params = { connId, handle, writeOp, @@ -612,7 +959,26 @@ uint8_t GattServer::attsWriteCback(dmConnId_t connId, uint16_t handle, uint8_t o len, pValue }; - getInstance().handleDataWrittenEvent(&cbParams); + getInstance().handleDataWrittenEvent(&write_params); + + return ATT_SUCCESS; +} + +uint8_t GattServer::atts_auth_cb(dmConnId_t connId, uint8_t permit, uint16_t handle) +{ + // this CB is triggered when read or write of an attribute (either a value + // handle or a descriptor) requires secure connection security. + SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager(); + + link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED); + ble_error_t err = security_manager.getLinkEncryption(connId, &encryption); + if (err) { + return ATT_ERR_AUTH; + } + + if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + return ATT_ERR_AUTH; + } return ATT_SUCCESS; } @@ -622,8 +988,8 @@ void GattServer::add_generic_access_service() ++currentHandle; generic_access_service.service.pNext = NULL; generic_access_service.service.startHandle = currentHandle; - generic_access_service.service.readCback = attsReadCback; - generic_access_service.service.writeCback = attsWriteCback; + generic_access_service.service.readCback = atts_read_cb; + generic_access_service.service.writeCback = atts_write_cb; // bind attributes to the service generic_access_service.service.pAttr = generic_access_service.attributes; @@ -738,8 +1104,8 @@ void GattServer::add_generic_attribute_service() ++currentHandle; generic_attribute_service.service.pNext = NULL; generic_attribute_service.service.startHandle = currentHandle; - generic_attribute_service.service.readCback = attsReadCback; - generic_attribute_service.service.writeCback = attsWriteCback; + generic_attribute_service.service.readCback = atts_read_cb; + generic_attribute_service.service.writeCback = atts_write_cb; // bind attributes to the service generic_attribute_service.service.pAttr = generic_attribute_service.attributes; @@ -784,21 +1150,21 @@ void GattServer::add_generic_attribute_service() // CCCD ++current_attribute; current_attribute->pUuid = attCliChCfgUuid; - current_attribute->pValue = (uint8_t*)&cccValues[cccCnt]; + current_attribute->pValue = (uint8_t*)&cccd_values[cccd_cnt]; current_attribute->maxLen = 2; current_attribute->pLen = ¤t_attribute->maxLen; current_attribute->settings = ATTS_SET_CCC; current_attribute->permissions = (ATTS_PERMIT_READ | ATTS_PERMIT_WRITE); - cccSet[cccCnt].handle = currentHandle; - cccSet[cccCnt].valueRange = ATT_CLIENT_CFG_INDICATE; - cccSet[cccCnt].secLevel = DM_SEC_LEVEL_NONE; - cccHandles[cccCnt] = currentHandle - 1; - cccCnt++; + cccds[cccd_cnt].handle = currentHandle; + cccds[cccd_cnt].valueRange = ATT_CLIENT_CFG_INDICATE; + cccds[cccd_cnt].secLevel = DM_SEC_LEVEL_NONE; + cccd_handles[cccd_cnt] = currentHandle - 1; + cccd_cnt++; generic_attribute_service.service.endHandle = currentHandle; AttsAddGroup(&generic_attribute_service.service); - AttsCccRegister(cccCnt, (attsCccSet_t*)cccSet, cccCback); + AttsCccRegister(cccd_cnt, (attsCccSet_t*)cccds, cccd_cb); } void* GattServer::alloc_block(size_t block_size) { @@ -818,10 +1184,96 @@ void* GattServer::alloc_block(size_t block_size) { return block->data; } +GattCharacteristic* GattServer::get_auth_char(uint16_t value_handle) +{ + for (size_t i = 0; i < _auth_char_count; ++i) { + if (_auth_char[i]->getValueHandle() == value_handle) { + return _auth_char[i]; + } + } + return NULL; +} + +bool GattServer::get_cccd_id(GattAttribute::Handle_t cccd_handle, uint8_t& idx) const +{ + for (idx = 0; idx < cccd_cnt; idx++) { + if (cccd_handle == cccds[idx].handle) { + return true; + } + } + return false; +} + +bool GattServer::has_cccd(GattAttribute::Handle_t char_handle) const +{ + for (uint8_t cccd_index = 0; cccd_index < cccd_cnt; ++cccd_index) { + if (char_handle == cccd_handles[cccd_index]) { + return true; + } + } + return false; +} + +bool GattServer::is_update_authorized( + Gap::Handle_t connection, + GattAttribute::Handle_t value_handle +) { + GattCharacteristic* auth_char = get_auth_char(value_handle); + if (!auth_char) { + return true; + } + + att_security_requirement_t sec_req = + auth_char->getUpdateSecurityRequirement(); + + if (sec_req == att_security_requirement_t::NONE) { + return true; + } + + SecurityManager& security_manager = BLE::deviceInstance().getSecurityManager(); + link_encryption_t encryption(link_encryption_t::NOT_ENCRYPTED); + ble_error_t err = security_manager.getLinkEncryption(connection, &encryption); + if (err) { + return false; + } + + switch (sec_req.value()) { + case att_security_requirement_t::UNAUTHENTICATED: + if (encryption < link_encryption_t::ENCRYPTED) { + return false; + } + return true; + + case att_security_requirement_t::AUTHENTICATED: + if (encryption < link_encryption_t::ENCRYPTED_WITH_MITM) { + return false; + } + return true; + + case att_security_requirement_t::SC_AUTHENTICATED: + if (encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + return false; + } + return true; + + default: + return false; + } +} + GattServer::GattServer() : - ::GattServer(), _signing_event_handler(NULL), cccSet(), cccValues(), cccHandles(), cccCnt(0), - generic_access_service(), generic_attribute_service(), - registered_service(NULL), allocated_blocks(NULL), + ::GattServer(), + _signing_event_handler(NULL), + cccds(), + cccd_values(), + cccd_handles(), + cccd_cnt(0), + _auth_char(), + _auth_char_count(0), + generic_access_service(), + generic_attribute_service(), + registered_service(NULL), + allocated_blocks(NULL), currentHandle(0) { } From d0c4d7a8a3ecad7095199857b79ce95e2efa24ab Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 12:27:49 +0100 Subject: [PATCH 146/274] Cordio: Forward server related events to CordioGattServer --- .../targets/TARGET_CORDIO/CordioGattServer.h | 12 ++++++++++++ .../targets/TARGET_CORDIO/CordioPalAttClient.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index effe2a5bcc..828341df2d 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -32,6 +32,16 @@ #define MAX_CCCD_CNT 20 namespace ble { + +// fwd declaration of CordioAttClient and BLE +namespace pal { +namespace vendor { +namespace cordio { +class CordioAttClient; +} +} +} + namespace vendor { namespace cordio { @@ -41,6 +51,8 @@ namespace cordio { class GattServer : public ::GattServer, public pal::SigningEventMonitor { + friend ble::pal::vendor::cordio::CordioAttClient; + public: /** * Return the singleton of the Cordio implementation of ::GattServer. diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 3d2bf6470c..cff00fceea 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -17,6 +17,7 @@ #ifndef CORDIO_PAL_ATT_CLIENT_ #define CORDIO_PAL_ATT_CLIENT_ +#include "CordioGattServer.h" #include "ble/pal/AttClient.h" #include "ble/pal/SimpleAttServerMessage.h" #include "att_api.h" @@ -349,6 +350,9 @@ public: return; } } + + // pass events not handled to the server side + ble::vendor::cordio::GattServer::getInstance().att_cb(event); } private: From 549a513dfb1b90532960258bd308db97d85dd5a4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 12:28:37 +0100 Subject: [PATCH 147/274] Cordio: Enable client and server signing --- features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 46ec738a0e..d67da8076c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -355,7 +355,9 @@ void BLE::stack_setup() AttHandlerInit(handlerId); AttsInit(); AttsIndInit(); + AttsSignInit(); AttcInit(); + AttcSignInit(); handlerId = WsfOsSetNextHandler(SmpHandler); SmpHandlerInit(handlerId); From 01e3a004a663470dd17a2d67428a2a382302e119 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 1 May 2018 12:29:03 +0100 Subject: [PATCH 148/274] Cordio: register server authorization callback. --- features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h | 3 +++ .../FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h index 828341df2d..f882fa98ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioGattServer.h @@ -45,12 +45,15 @@ class CordioAttClient; namespace vendor { namespace cordio { +class BLE; + /** * Cordio implementation of ::GattServer */ class GattServer : public ::GattServer, public pal::SigningEventMonitor { + friend ble::vendor::cordio::BLE; friend ble::pal::vendor::cordio::CordioAttClient; public: diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index d67da8076c..10bd791c84 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -356,6 +356,7 @@ void BLE::stack_setup() AttsInit(); AttsIndInit(); AttsSignInit(); + AttsAuthorRegister(GattServer::atts_auth_cb); AttcInit(); AttcSignInit(); From f79eeb0173856a5286b8be00f75c8630fef2b964 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 2 May 2018 14:32:38 +0100 Subject: [PATCH 149/274] Cordio: Update stack and pal to support LE security mode 2 level 2. --- .../TARGET_CORDIO/CordioPalSecurityManager.h | 6 +++ .../source/CordioPalSecurityManager.cpp | 49 ++++++++++++++++-- .../cordio_stack/sw/stack/include/att_api.h | 2 +- .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 46166 -> 46166 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 94784 -> 94784 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15676 -> 15676 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 446334 -> 446238 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24540 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 52210 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8668 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270828 -> 270744 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_core.a | Bin 48498 -> 48498 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a | Bin 93270 -> 93270 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17880 -> 17880 bytes .../TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a | Bin 451132 -> 451072 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 46254 -> 46254 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 94840 -> 94840 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15716 -> 15716 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 446758 -> 446662 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24540 -> 24540 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 52210 -> 52210 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8668 -> 8668 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270828 -> 270744 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a | Bin 48542 -> 48542 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a | Bin 93298 -> 93298 bytes .../TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17896 -> 17896 bytes .../TOOLCHAIN_IAR/libcordio_stack.a | Bin 451344 -> 451284 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 45796 -> 45796 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 95978 -> 95978 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15508 -> 15508 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 454960 -> 454864 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24248 -> 24248 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 50834 -> 50834 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8652 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270284 -> 270200 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_core.a | Bin 49310 -> 49310 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a | Bin 94644 -> 94644 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17976 -> 17976 bytes .../TARGET_M3/TOOLCHAIN_IAR/libcordio_stack.a | Bin 462934 -> 462822 bytes .../TOOLCHAIN_ARM_STD/libcordio_core.ar | Bin 45872 -> 45872 bytes .../TOOLCHAIN_ARM_STD/libcordio_hci.ar | Bin 96014 -> 96014 bytes .../TOOLCHAIN_ARM_STD/libcordio_sec.ar | Bin 15528 -> 15528 bytes .../TOOLCHAIN_ARM_STD/libcordio_stack.ar | Bin 455288 -> 455192 bytes .../TOOLCHAIN_GCC_ARM/libcordio_core.a | Bin 24256 -> 24256 bytes .../TOOLCHAIN_GCC_ARM/libcordio_hci.a | Bin 50778 -> 50778 bytes .../TOOLCHAIN_GCC_ARM/libcordio_sec.a | Bin 8652 -> 8652 bytes .../TOOLCHAIN_GCC_ARM/libcordio_stack.a | Bin 270292 -> 270208 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a | Bin 49310 -> 49310 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a | Bin 94644 -> 94644 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a | Bin 17976 -> 17976 bytes .../TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a | Bin 463010 -> 462898 bytes 51 files changed, 53 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 2840a87365..4d25791c51 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -22,6 +22,7 @@ #include "wsf_os.h" #include "sec_api.h" #include "smp_defs.h" +#include "cfg_stack.h" namespace ble { namespace pal { @@ -252,6 +253,8 @@ public: sign_count_t sign_counter ); + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); + //////////////////////////////////////////////////////////////////////////// // Authentication // @@ -322,12 +325,15 @@ public: static bool sm_handler(const wsfMsgHdr_t* msg); private: + void cleanup_peer_csrks(); + bool _use_default_passkey; passkey_num_t _default_passkey; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; irk_t _irk; csrk_t _csrk; + csrk_t* _peer_csrks[DM_CONN_MAX]; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 994af9a621..29a6a5eca4 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -33,7 +33,8 @@ CordioSecurityManager::CordioSecurityManager() : _use_default_passkey(false), _default_passkey(0), _lesc_keys_generated(false), - _public_key_x() + _public_key_x(), + _peer_csrks() { } @@ -53,6 +54,7 @@ ble_error_t CordioSecurityManager::initialize() _use_default_passkey = false; _default_passkey = 0; _lesc_keys_generated = false; + memset(_peer_csrks, 0, sizeof(_peer_csrks)); #if 0 // FIXME: need help from the stack or local calculation @@ -65,11 +67,13 @@ ble_error_t CordioSecurityManager::initialize() ble_error_t CordioSecurityManager::terminate() { + cleanup_peer_csrks(); return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::reset() { + cleanup_peer_csrks(); initialize(); return BLE_ERROR_NONE; } @@ -287,9 +291,40 @@ ble_error_t CordioSecurityManager::set_peer_csrk( bool authenticated, sign_count_t sign_counter ) { - AttsSetCsrk(connection, const_cast(csrk.data())); - AttsSetSignCounter(connection, sign_counter); + if (connection == 0 || connection > DM_CONN_MAX) { + return BLE_ERROR_INVALID_PARAM; + } + size_t connection_index = connection - 1; + + if (_peer_csrks[connection_index]) { + *_peer_csrks[connection_index] = csrk; + } else { + _peer_csrks[connection_index] = new (std::nothrow) csrk_t(csrk); + if (_peer_csrks[connection_index] == NULL) { + return BLE_ERROR_NO_MEM; + } + } + + AttsSetCsrk(connection, _peer_csrks[connection_index]->data(), authenticated); + AttsSetSignCounter(connection, sign_counter); + return BLE_ERROR_NONE; +} + +ble_error_t CordioSecurityManager::remove_peer_csrk(connection_handle_t connection) +{ + if (connection == 0 || connection > DM_CONN_MAX) { + return BLE_ERROR_INVALID_PARAM; + } + + size_t connection_index = connection - 1; + + if (_peer_csrks[connection_index]) { + delete _peer_csrks[connection_index]; + _peer_csrks[connection_index] = NULL; + } + + AttsSetCsrk(connection, NULL, false); return BLE_ERROR_NONE; } @@ -695,6 +730,14 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { } } +void CordioSecurityManager::cleanup_peer_csrks() { + for (size_t i = 0; i < DM_CONN_MAX; ++i) { + if (_peer_csrks[i]) { + delete _peer_csrks[i]; + _peer_csrks[i] = NULL; + } + } +} } // cordio } // vendor diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h index ba81dd509d..2ead0ed962 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/cordio_stack/sw/stack/include/att_api.h @@ -565,7 +565,7 @@ uint16_t AttsCccEnabled(dmConnId_t connId, uint8_t idx); * \return None. */ /*************************************************************************************************/ -void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk); +void AttsSetCsrk(dmConnId_t connId, uint8_t *pCsrk, bool_t authenticated); /*************************************************************************************************/ /*! diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_core.ar index c21f7fa70b531cd113b163c47413b8903ade27c8..1597a2b37daaf042b9a2a67293a3eb0f43975902 100644 GIT binary patch delta 188 zcmccig6Y}|rVXB~?50L$#wM1Qn*&%wg27GeX;z+Xk1MPRaE8&0)1bE61kP2MbpB4D*nh7ADx Cu``PR delta 188 zcmccig6Y}|rVXB~>?THrmIj6m%CHgiE$ zfCR)hueKHwMiIF0S0xA&*qo413$p>D|5wpw5tuC4z*Ftb+$aKBlQ&DD2w1I?VFLi@ C2{Um3 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_hci.ar index 0eb5535a3a2bf26d1ad24357508b18193076d2f5..908338594d94d69c7972046a2849b9ddc3931727 100644 GIT binary patch delta 127 zcmX@`g!RA^)(z}D?50L$#-;`aoB4Q5wPBped^}>C6U>WiQ3O705mtu^7=l$O+!4-3 a7T6x(&REZnBJw7T(U=oO#3q4}MF;?o3m`%O delta 127 zcmX@`g!RA^)(z}D>?THrmIj8VoB4Q5wPBped^}>C6U>Wip#o-Lfe%}R)lmc#?g(ci a3v3T?XRPN(5qT5FXv~QsVw1qgA_M@Co*+s9 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_sec.ar index 819640e3da3fbedae33d19d7aaa5d423a61603ae..3eeaf263bea3205d0a38da0e34fc1b355ce88efb 100644 GIT binary patch delta 59 tcmdl}wWn%BFeAIEk(sfnf#K#T#zX-)=aAq=9yq5;ZXrLMqogOr4*(BR5DowU delta 59 tcmdl}wWn%BFeAH(k)fr5q1omr#zX-)=aAq=9yq5;ZXrLMqogOr4*(Bz5E1|Y diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 69861e6998fbc21cb25ea6e381e05fccd7906c6d..5825027100f8f4918fd7929f31d6dca8e55fa435 100644 GIT binary patch delta 5498 zcmcIn3vd(H6}|WEu58OcSvHo8{E=-UOJG3YPZS6NT*k41FtkZpAT*&N12ofV8Iqw; zHLMB005g0>i5~;84edy z9Hg(qxd%YH8C+Wnk{RkiBcbJ?OCSN?Pe3+s?^Td*gn9<@O+&qvPW}2cHG=%V@Wu~8 z7C8Qj8SifZ*??-?+=#y{1o<|g6d!^FroRS?!2BmoPzM@c(W?)DawpJk0mVQU<%~lG z<#NeggJr~8_mVZ>*&v1kAwphXmZX?WRhS90LU5bA$Gb}N@c4!)Y!=*bFoVqx)(uFv-*s#Pn7zj?wgCi=a2j$xMf&zO?hO!g`LR?g0C#nus$z| zo!(zl(uvXiHAU|#+cNzPd;9)*y-x;bWWhYx=3cpQrC)VFPX2q%X-*(!#YXh!C zA8*=#6+;SQ-M~9Cfg& zWvi7n@>*#f+k~~*&$4=sTd^iLfB;jnga3`yP;3jIy%iVmnaLJwsAsjE&v=!&`R})4 zekkK=VW{UyN$AL|Y;_Eyy!s`>Kl(=X(*Ot~NT(SMNSos<7SBk;*?_n-puaRAE~~Ky zxrqewfCfq|F6JJ;lmT%|EH36BzbxR8F8K@IGCO0+0$Q>K8{^OQpY7AssI2wF^SXfKHRng#9LMg%*=eg|{f7 z$SGEdfdcz=Emnnr1+rJ zm#|zN2~bFmwH)9n!S?_>FW3jLU9cCRP4_zl4+D5la4A4kum|8{oqLGI2$yyKLhx{a zd=aO9Gz3^j0X!*~#9rb@#Xv`dL5bcJTn6x&U@D|nFm=qO^$-KP1yehZ&anli0q-Zx zMgU9_OnQp8su7nXR~j%&E7*odSt#SBw9xg#$^7bew6Q4=^7rNP!X0SCS)ogZ9lVxq zvlh{CqDJGAd23j9C@+%kppNg}fu(qspWK0Etc!)*pXTz6mnl^jFM1iv z@V=0Gv<$cMACX{xPY$(R@GxHrk8YC7FhwZb#WS0*Oo^sYWzX`}#`o zVCT*tChc0!PPf;vPDy*`XIN>;KTB1azKc_`m$13k?BL|odaiy4@8`3BiR;xjY3Ynh zeCLk!(_(uZAzhj95X^BFiw{f0*?_ndi;Gg?mjtgT+KR6Vs?caM7_2pE33B>r@fo>h z@1{30kSYNFgR6cKJ44i=yp}cH|4XA*!@9iQ{g(s=DZHCT%SM7$=zY zbe-o2rcb~R^!VGle@bu;fXE}_-Gap)qx@DUfKzZDy~={=$6ge~h62z|j*Sx#OnZI- zv1%OxutFHw00#t9qF7=|6cyS5a6vF7%+LqO*At7Gu_FEZK@*^@9ZTFOnEJn__xr72 zDkLIU&o2t{18D#L6~2i4RE6B3&1*#k`GPiligwalZL}*E^Gj{?(mpEzJfVcz>Pzrl zvA5WWlu*M_53b^y+i4qh(KfR2gY8(#K1=1%cJwH7(*S1iRxfSYU(;=XpIm66Xd3VJ z${yC6#vAschozO_MrIqXWRq2lMSpSxLMNy3Vq+oCnB-8i@Dr?l3mnKf}r(>gY?hrXNW)6qg_z4A}l zu58_^$yV%RBGYl(48&{i{DxI>KoYDD`-PA2l``&2jv{7SayvB#eOXrNUrEX1| zD^(i>Rq~!@OP;ptIcb^S$ga8fNbPn*#SWj{9n#@E!x4$|w9a#qH<5VXzofqwCE~Fu zNG|z8VhZtDr4E-LPgvUGfUIQceX2OEi$e?5%S#_IEX~#|cN!<&s(6OJH{_wl$+}8& zpODWRbyjg|?$BIa^3nn$gLsTit?f&Bjd9qoid&DAC?|}ET}2agXyYGJwi_q(s`$!% zK3^GEY>EF#;41wk(5A0ZMwaW2M$R7N4?=Y;$F%dxREIuxwHU~ug)b|$_Zrr|a!bl+ bLuj_gEN9XU6>lwl-|}&lVQKVWHu?VpcpM)s delta 5527 zcmcIn3vg7`8UFusACP5}EO~97WRt~YLn51OLP&rj2}%iqXzO$sgi4_xTBoE=he9)O zLkG$uBS>%YR5T&VC=RxeO>D1^4$W9WEZ7F*B?w6?BCnxw1UpcM^gny=-R>^bhS#0> z_B;RM{QrN>x##S;EiGBsTC&>SMeQ}fO%^&T0q+EkPY3KTwEjBYB|oj-mEN5KwEj=k zT`54jiM6_e1+bKb5Q1hmV%hTyuv2^AbR%@`0O^}> zv<0M_!Ie`WMMH~Kgk?E%KZH?q6l5D!-vjwZsGAM)O+&ktP7!^YzXth#;qAYIEbyTk zjbmp)wxQXL8}a3(Am0X*{Co&wiUSmZIqyY5i&b1FugC=DP9QiB6dT7WrU?y{i@&&Q zP>WB&H$(e>4rHJHwTb!rLA?`bIRvVW33lW5xTD??^bM#8lvS6ORq9LvV^$2Rlcc1$<+dhwG&OI0P(8}B`c8`veB^Y?a8vsssA^3q{j> zNgy7jB1As$Kn^(bCXQ!yy(L*S2KIrY<^)C zP8caedDmwRrJ5@bHunANS|9j|_q8_EsJ??RpmjAn@K&vNANIUe>-kvuO=4+dyYP`A zgD+W)IdP(ljJgNXo&4q1I5%e~6*7ykY>~HU$-ds-<05DNBjX>Ow6bk2x#X?EWjKs) zUW4WCArsA9!@ICS_@qygCp=3&=hk4Z6M8axgxS;J&EsiJScOB4sZH3b;0fOQ9Hzw8 zIFcJ`2F*=w(953_j(*7 zeunU#S6ROP{}tp^25vqoR9XWlA%z43AunP;5)CLhO4b-$3wIVBB=~2PEW;;JvI4uJ zWECEbkb!2f&XPp|NCo&K>g`OMRL&{{X#yO1}C~BEa)ZZ(N+uP7dbdB+TL~H(^5f|Dopt z`hTbp{|`9B=-z~!l~1E{+(+lQ6gtNxc!bVzQ00R@%{*(>uGR(|@bYT;K(JQcr}QLx z#~B-5!3s6)JXKJWyy(A&=l#jguz9@ub=;#x9s%NzJR}w^{2+Wxaz$8&5N&56yLg4n zhsD^XkX__A9|`^#_7$s)8oU~%V6Y)dmcSb!i!&%LLKbI`c(3gT>2*773&aQmUM<%xvqDpZ@?B)$;=ot9RR{UJc2B5704%*eD1d}}3;^~6j08d-? zy_SBz;8c2bE&Bz*IrKwm92o%Vf-~v07MyI>#j*hCObF$v5}XS#k63fiIki+MQUKl& zOo2jyDNv7)(*e#3rho}nf@~|W7$EalCj|{)xbUOEV+GTlW2<0_vqLcT?-EP}iIYa; zq4|)2Wf`yk7GFSp_Ni&y|8wPMy#5804P`qba-|LDVlV$u8*QxRd|ewBs;g+{KCb9( zb@}*(*rx2hIK6Ra0dnpSVxiJYJJG`*3!;~~oV+neo37CbFpW?3$zJ6MHOKJtH@8oki+8qTk-c*ax{>7!vn6pqa~s9S z@mi&=GD=g}r9rl2-p$5)*pPfnRc+qs8f#h5zSC8kUQ?f94*LdIZOm$7Q)b$IblR`R zp404=WLv{2joWCt$|~(mT^(}jc1ZhOwo^#+w=5|ss#}JEe(8W+qLuusQPNTC+8HP{ z>pAzBRB6>is^?nN45Ma=w5ZgK9w;?BeZIsu^3m>&qfJY)}=d8ZglRJkK1)taPoE=?;evE=2!tL%oTa~vb@6j4hUGPi+Re2 z)>;Qfh$Y_hV^y1WNQnA4=sQAXL*G(vnXq#Ng#EBBUI1sS=}ZPV3*@wQ~TZ=SE78eyrb4O*JDrT+nkLJr&j diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_core.a index c550c6953c37e1bc27d0eb0ecec8a2661244d25a..07307fafa11ca6e3e161788615e0cb179375d796 100644 GIT binary patch delta 184 zcmcb!pYhIq#tG8wrbcGQrUr%^m9Da|LD-W&%1Ue&WmV&V@;5v3?qY?p8HMk`*pnT3 zB{u(+cn8zB`J?P1E@U$)vyXK;4}veT`J%fT8-g#sS;ViK L51GFwMu8asMh`R@ delta 182 zcmcb!pYhIq#tG8wCPs!9mL^6Um9Da|LD-W&%1Ue&WmV&V@;5v3?qY?p8HMk`*pnT3 zB{u(+cn8zB`J?P1E@U$)vyXK;4}veT`J%fT8_YeM|M@QD QgK;MRV-efDCq{u802VAYjsO4v diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_hci.a index 0a269a1b376630447cf074a90924899c6ace99e4..85bd5a33fa214a07ca3ffeca883f3aacb0f68b10 100644 GIT binary patch delta 127 zcmew~o%z#r<_XelrbcGQrUn}o6S&zSOvA|^(#1B<<1Utf3rwgH->k2)%NZuH`9u0l p5jbZ;O`rwTn91+c#W(-kQqKkB_t!{lp1q%o1;z)-A3AKn0RRVRDQ^G( delta 130 zcmew~o%z#r<_XelCPs!9mL?k&6S&zSOryyk(#1B<<1Utf3rwgH->k2)%NZuH`9u0l j5jbZ;O`rvg1J?U*OFb7{0Hk;Jel8Zc0Lb)1hYdIYg|;e0 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_sec.a index db45e9ec8cea0e31ab97d7e0e6bf4b03308a5b6d..a3dba57788256c014d39668111fe0000e88dbb84 100644 GIT binary patch delta 69 zcmccPe8+i$G@GfBnX#$CMny43D08zd<1Tg>`!B~SHW>RX|20l1d-7R+iOmNkr8xkz C4HMY_ delta 69 zcmccPe8+i$G@FT$p@pT%Mny43D08zd<1Tg>`!B~SHW>RX|20l1d-7R+iOmNkr8xk% CjuZR< diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 5a2187d27ba83873006414fecfa8054a1d13bc33..82ae3644ecd0190c7dc340c59d0e91eea48c09f1 100644 GIT binary patch delta 4861 zcmcImeNa@_6+idBefxndE(^Mk4`EqMK(M+(P!eheh{5>L77WuSXj>y>#7GT|HbF@8 z@M|iCSm0KlN;0*hox%7q$g0mttRoTsXtnJw$tKOz@gqZ(bc|gMF-Amt?qlBy#x~#w zGr#%0^SkGqd+vSbu61V>&d(T%OI1Mb#I<4|9Q{4_1R9YGA;^P`;XEhy0)2px zwPZOxK<|bb0igd6&o%-b30}+wIu!Dq!fpGtwLo>e*#=a{x&=V*hK6fEM-2I1f(FGL zF$4WyII#jKN7vz@I8_Ezhpa!`jW50q^gbZaN(kY5CqdxIEgJ&)PT^bjym$~E1eO$n zpkw3fAPhhTq1F3v&{+Y(cS8OSr_-GvaC8SA2n-^?5ait{jM!#B&l%&X4f}Pfap1GY zW6dlX9sI<}@GQ&!siYgq&3fYSd|q-jDx~c7qtd@@Q`k^t-^%<^A!S1X`b4h#p(&(j zQExQ7dfP`+A~!z~QrMAGlINxE8>50%F<*(~8K;hQ+_oK_!oMw!(Cwn_F`kc4%^KwI zFl1&vp3(erDyd~l0!!s62pm|~2F=aY^Q-N&MQUj`!f22{*h$!}uW#Oh)LifCnrDsE z{h4yoERqvPPDsy}!-OnvN6pLQt?E`I{A6D? zjCR+y^E`%xc<<7Jmh}Y-g;h_l%9LS?u>1)y%TugwzU-F6=8$Y4lC-)U(kxzgrUXgA zSIF62`Ty(^+X8#UU{D7$9+gLmlrwf zOgniBQ$mzC8CKWWGMh|^e$$pemp2r^gjjDq}!nddIVz@oaUa_;zkO`Pdd z|DwA0%VTT(7xu)oE<6`JF+Vl9#5u90C8ezP%6PXByt2H7ba~~>foq|f)=@arKKdND zJzifbVU^FAnV~n=dI+;oFv26q`&m(MrnOg7%$jnMHT8Z;vRO=13fuivrBYiW*p#`S z5u4IjA{bcrocN@_pgTcKMA#t=K0((1Z1`|q*;gVsEd0?95g@WXS9h~BADCF>*E{5R zRKrpL$~e0KR&!1Tc$@PCfZd!;SQ#=M2av$+WB@nkG=PPiF}|5I9$_ozbbxm`V_X+! z%y$u)#|JoLrP6?%2)qC~8o(J`7|(eW0LB2FKZDNc19u>1GUWF!Z>$8!GY+qlBScY1(rUg(dX5>Z+sbZH; zI#})v8(F}L&|a_EjcAv#Kio(WH)Bk;7IPN0&FnJzNUZ6vDVDhcmWvpxM9vcu#R?-H zhczurCKaryKTV(cj{X=rWhzd%+-k?-L+f8-!UC^h>#-VJl1+AL3Z%yQ+G_-yYfoLIDd{7tdsn{Qmjk14CK7Na{$37~ zV=*QPY%*bV6KsTJaqFR(Ag4a!6f{h&w@Bz2S0DR1OEI>Chbp#t7<1)C8aoT{y09123 z7GN7^jBn)}2hh$L^Yn1W{Jbt)UkVBQ0Ta8CDRz4}cfc{ioLT^Hc)p&^IT2tkXH4)M zXDpy9$Ok!N++og6fX_H%0XKtsIAME_=c+$5lCgyJF!DvR7>|>Zt-NC*$*gjtLFqJ+ z@uXP!+(c4Hp%Q6E+O0g!X`%80r?b4hjnM|Io+^90s7oA=y?vEMHYAg9g;h8oIY4MJD>d4qzgscCH1XRvMEv*@CQ@P`xQAjcCav}fn-GA7948X zHu6-KE_C!u>Ty3=X3+({ZQ&U*U*ARDcb-f#2Uis|B(?t%IimZk9oNVPanQ0ut++{Y zY=af0p_EKi0}*toUa9(mlU|A&`lIaGczKy1wTSwm<>hs21^om>e(Y9$gLVsk{6)ozU6ErOp zrQJc^hx9k0JMf*N_RxvXouH0`U(iqV7pb5isb5jy$#gv@`b%ojB%wM~x-VB~51ou> zP`Aw!9Qv2fKnnj7A!6c?6l9YyRsZ_oJ`S~bryz&!RZ{|;LQbq6rIj-4j1UpJ6wPPF Rzl1Ln2l+VEwW6Us{=YK8{1E^E delta 4961 zcmcIo3s4m29shsd?%o4=9CyI2o}LSL38$zWLJYoA9tN1Gsc2`4kI4`*4aSt>BZ-2# zXk{u99Pv|Ez-Bbq4vujKxtL=*t%IYTNhUVEGdY`DhCs$hI%6D6O{FTP-?w*rJYpO0 zu`|E>?eG8E|F`@7_ipa+dDHdtrhPVj#>}+L*%`A=Cp93s1z;cuWEA1Cz`hC4Xd#a_ z@Cn7qqwe&{G$4=uRy~mh2jvE&NjYNM7Acp(%9tt@60E8hA6{9(q3IIPw z$ZD~9^8h~x&o2P{|FG;T;IZJ9TEN30k2DPGw>}4~LFNH#sBQ)PAk-}aJZ8ublQbmf z>?*+j3m<<7nBh~?aCEi<)*x#q58~@Sz>fe9Uw|-XNWd{dp{fwjkh z({RuSTo5vFC!9|P7dn9ZQOG|M^o0ltH6j4{{`URvdHb`z^Oew;DVq|R23M;8-O6RU zX#w<3b4|>1AGDeE&d)qKPCq&vqtqBAxTgEK1tUU(Xw1*cD;SNU*Di>s?94| zFac~^3b)v>kzXnLH}BuFQk2cQCUL`Zl4JW6rEe^hYK$jXlFn}NIbdg{DZO4V1&j?J zmDc9L6q_%xMykYz5WUQ$Bp|=Yn+vV^lG?fpoWb=uklpTsN|afY>rxwtqRZK@GX$bu z`1x8$<$X!ChB2`{|I6O-usXG-yp&zgQ)$y*39PR1luoF++$%IL%l$@dDemcIt5=UC zVd09^jjPG-Z=LQ)2g=ON#RVN=c5!)r@D}CTBc-BTwD8=L@_d${>5iiEe2>rXLZrOF zKq7BtMIEPJ3_5s<@=A)fs1-|s0lo>nNleNvu4%@N4} zQyIGeUSymE@H*ou0J|Ae=V8Wr+A3u{2|!}n0g%Z!B@|EVyu&nI)9)G6w%QrfyiUfn zUO#1)e~GWlLa>hn5Je_-8G>_r2cNQlJ!33l>_hNIO4l& zQi_*io?N}_MCIh>MJti+nb1~}b}t!Ksk)r%U1Z0-WMN;pR0p-~BYqlVBK3bsj#|J0 zxG56ob(6^YGMlhTM_VWLWe!wJ)(=b_d^L>6voh)2%bm1MdI%XRxgZ9j>3~_mQc=^o zzd|6D>bsz+O$Sl*9_df;p*O+H^i9Awy2Eb*m%q7EPBDJ|ZY4MWR9kaRtUe-eGH2YS zD9P6Cmf5BTSD!yditCP&PUgh==fXHTO`;soH~h5}QsaDxxMh3*4uV5yBS zUFWkT;SFhf%yW3vVx*(UA?YHy*=6)3YAKuXtgoIu)pO=RD8URmSeCZ_$FI@G;RKg@K3*m!6M z+y6H-L7C}0q^CY!xxu0NEMiO-usOsZFs6BbWSkgknAX1^vPZJ|v~ifRamz2g z0Rb&UWYbQkP(a5vOUd?Q2l0I*DC_meA?&8MA|-7XwkYrEk%>)`pqyi#Zt5vkb}-L9 z>Orq7X>+kvaT@6Pbv7h|#M9|kUN#^Hk(zlVsMC?9oHC#x<6-sQGN7NtYhRtQby)Nk z+L3+!FiYJ^v{(DSR?vMUdS{oQL$O*+{S9RGUf+bg3BxQMdr*3uW>G809z{9NXcn3! zde;X~nNhQ-F#}y_Mfh53%p2EGf*};+rIyRX6RP{sn}X)1%`G))^;oA0?KH)EBpR<9 z-mX)^f3t{w$+V+{ZaI`-3SI{#` zSwFoaJ=^hKUD&kuV_J4^HQqKNYDyjc)~!X6=ya=h_F4R5lxFeLyzIf0m#)#m-(13P zYwdcsbz-wgi&nY})PL$az8oJmsl6P-+;b_KiJa}UdIzR+71|QK+p@T}Sj`}P>;&4Ap^BCP!a$ovDMvw4yE70R+G{7nY# zJTUo9woiqjY>?5LnF4K5_%SKmNPO|lt>wqWkkx1O@xsgo>z_26RSH>t%hrAD0R2EV AVgLXD delta 195 zcmezLi|NxZrU}yQCPs!9mZrv&Y{fQO>}P>;jey+EBCP!a$ovDMvw4yE70R+G{7nY# zJTUo9woip&Y>-(@fwnL{$g0gTDcneW@y)H}$HbuO!SWe>yfCxD{7JJ}rI6*fY~9BW E01nzVkpKVy diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_hci.a index 4ea76bd287b4169e65a7e87e611b058d044baa57..8551f1904ce7b74ac75767553ece31baf96ffaca 100644 GIT binary patch delta 142 zcmcb1gZ0`C)(O(=rbcGQriO--6)uQxwDjPH@C_`1e6h{*xH&aZ1df>GmqK+IfK>#n sI;jdXVza^p^BfolB)h%DhH<4Jl8D518$U*Fs2yNC#kQwJGJX;Q086+k?*IS* delta 142 zcmcb1gZ0`C)(O(=CPs!9mZs*D6)uQxwDjPH@=btzvCZ?iIW?gIreJ|1Ci$f(0s*T| qszL?KHY;2(&w+A4=80`Dv0+>(h$JGh-NuiR8)gSYO-dx=Cm{e|(JMj# diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_sec.a index 97bb57537d43bee84679a44f9c29aa6d7364e9d0..3f77c0f0a62c878a491a0a9a34e9c70eb597dfe0 100644 GIT binary patch delta 87 zcmcc7&3L1mae_3vsgaqnsiD#23npR{E&fBfhCr_P=1|660?6{4b%dt!p$Oblcr6SQ K*nGi+Ll6MORT}{S delta 87 zcmcc7&3L1mae_3viIJg&rK!c_3npR{E&fBf=0L9a=1|660!RX4n{|Yy@*!*3d{5!E MFic?c1rrWI0M0-gK>z>% diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0/TOOLCHAIN_IAR/libcordio_stack.a index 80ee170a107f92383a8a9c34d56e8299939b966a..3352eafc4157f8ab88bd7d725dfc942175828bf7 100644 GIT binary patch delta 5960 zcmcIo3vg7`8UD|?k7Sb&cC#V75<+%an*@l-K9UeZMjk>EFe;&nRd5U?);KCei9m^Z z3Gor^h=gr(f)5l&5zxVf2zP9;8VHYZKo z=l{<6|8wqn{P*5$@6KG>ow+hIq1ay%C=U39%c3|ok6p&Jd|)9Hd$t2RA2_}R*qK5* z(}owQop#0}y)XmN&U~sa$N;pnSgZ3m0G_oN3}~^!Kpwpt__?6^HsEIg?FWq;w*fy> zv{wQDWzc?UfV1;I`Wo;>_Qx^QV$foRA7Lf&b@)XHRD%-3jq^Yu+|}C;+Cbq4cKbR| z&Ifj+f)c~=ji5xKfvS9cVNjM1>d!*^nMOAc1(mR9()q#j8$pf7qZI-JZ7vbxV9#jA5QNKe=~vw=NF}muwb(L z&j7$70hS@tRf=Gs!o$de7{Hg}--0!{Q?MAl65x2Oh%A8(zDGVK+B#S^OBI`mhKU12 zdE#UTdt^{Gk2xejhqz}o%XV+*3r8U=@Rxpe61*)oUB|LV9E+3FFv!;fY{td9Po&|O zT-4VC0JY1Dvu$V>#M`2c%l2z3;w5ZyO`J_3W}`h4k%HwkoS*qv9*jse?ItW|#nrFC z^0#`|qwFyzyq75!;hC(A6XJ2UNFV+Lds@|+wzh=Qp?1mIB^Ex#SziGU4KBT za!bN36_!?huz3;>kM3!mH1cgDrgy0kO$B#Y>S(AfZbr4Wp;?;I0h)I~eFcBW4T(N4 z4DwQ^kt%7mMYFI8PHSm%J&csYK8RFN4e!AcvKnf5rFpSuB!n9(d$&Fqid@NBEvjWu zqthx{o?%;W@*06~%Y+k~fO#U||r1#UKX;#>?nb#E>GCe}4nMlJ{D zbf%QDT7D;5(|}pglhtB*DzHQ>Lw!SK15P$w-k|L!hxqHW%x+O|ZH+(i+^Z}{Jadmc zL^#*6#)~|F`v|X#qiY7g!u29MM?AZZWou{-BQp;mn|LI^2;zJI^u)bxcmgPf1b70V zkaP^^C(Z#VCeDo>5%M2LHu_&mTmUeh82g++j80RCar;#ujQ}seC7HN-;z zW)K$!-Bkr*(;_J)gU;kc`|t0Q@0T9nE7(N)LVmsdZsDG(R%LvNbyMt3_bKYTJhm1!rS$w#W z&69AQg{@2-(w;2ki|~6qPi%UgB{Gj-@AFLMYK;82_}DLbc&{oB+|F|N2PvZYH7Q3q zk%FCz=73~hwa;o;(}QhW?V_-fTSe_I<_u2XXB8nV2#q8v1)svEmtmLJ25YXei#Jhc zj|SK7&*h&F7F}H!^;@j$4c>8uJvd>%m49v(y$jWhVDCOFA7c~ERXm4R+Qi8Q7S)7J z96*gdCweM*F8|af+*8r~Dry#{i968bwLqKoW5nD(ADVVlM?#O$No%HK^B zH9K(t9^BWZ!qv__%B*w%tLQq4#apr1AP&rt?3qb(8XFhfxaiJX8gD9?U+8kVe8qm_ z`RglfKcP6KF@EC-#r~*kA-0OK4&iNNnI(I1>i6LqL@yP>1MIia4#(9WM*AQS?$?|N zX&}fD%eJstY>fD5iDPz9 zXsWN+vE1r*X-4{lUmwsT+u0T_C3q!qayiQo`(I@t4YxY(9{`t;u>c=T#uJIMT?Xlx zP3Uw0w!_n5{21vDe@2k)0%{82HZq!#GVyd7389b}{f%^o!HUUtn&}SD_Bb>(3T)&% zj6RVXU|>ob6u6QY16L8_b8;#%CY39R@hHX8-PL4c(z%uxM|(Xn#=C(S&u%R-#+^&- zGEz1~@REQBpPc6w-W4o`$zpRCOP4fzld!!dmy25;W+}qDgB{Y)gA!_TGC-ZlOOTUr zZzVB~sGAu5-!tu_#BP9eT-_v`Dkrj* zjE|Ch5^xTe5@Uc?Vw}TO#Mt3BQ{PRD9n%iyn7(Ky^AP}_k&aVwj2PR0M~v;#aT;j= zMZ{QNPK;AnMU0ps;q!$menSGz@jT*eae60P!)nD7-OQtCC^?MWq_ktA`)ANs?O`p# zwu|K|9eDGN!DbXv#2gfuRczkH9PQbXjS9Jn74uA;k%W48F)M2nY&Xm0-GhZ~KFd)K zVr`;mJB(@XLo2159F{NEVhg1l56}$s^RN}-B)P1yiL3H)SFha7to$e@paLZ$xNo|Z zpR$RzJ22K{Jf2Q5=ZNG{W@Bzi46>I!tWJEqhmA7dZO0mKyLo%r`#CYi_&24VeS)no zh)G7H&$75LHKw$uGKU_>=dG@&;`fr9Q~#ivkIsupMkCK%ywQC7_S08_{!%-iH6!}+ zO@dRuRENtwrn%1KYE)dTcm<~Gpg~?qL+sxJ=RZDv35&)hW2aouOrfeSfC=~ zF7H1rt?X0i9&mPs%c{-ntw={{QS6S2q74p>mrt4BGJZkdHu|v|dC$yPPsW$Z8|&p; zhxJot?vjIjUPc@BT{)26zs(o&&MZ@Db364h7Nu@foc(e@k^Ant%Pl$e!#65*=7*QR z)VQM?7AhUF#l?pb{_9$|3uW49^NviZX@_#J`AO$5-F8Bm;xOySw!fe{^*U9J1Y$}w lNOPHb)bt2=^@f{Ow>d2Vui+9}q)si0x&(aNUQo+R{s;Fs!Uq5V delta 5968 zcmcIo4OmoV7Czs1=Ux#=28Nhf0hs|BAxQ?18MN{T3IC|TE!|Ch#LT3u#AMN=_JYRFHU;tW7N`=z=l15nRluP)#KcQ7B@Zt;gs0gr%c2&dNpM@R##k#Mzw)EC~DK_XnEoF8T%0m+1FHqMrpy#dk% zgsLZNiv{WXuq_DE|HJ<6Ae{@&+yGJ})V@NmZ5hO&7rAb*m>9JVEZ>KUKY`_(p`K4r zSWN3`u>26-#z7PI?1{u-)J&*m<9k@{ufR`2!E%sI%-jGnp*AN1YG2_ycJtpsz7Tk8 zBFHAXz5qD{6%-}^;$TEMC_f7IN1WzP0fn&W*B1sGzW^m1#o@;JwY5^CA&Xq0E=;%33O#-E<5Npl{Nd( zr+5lGmTW3{XHY4>oAqRbE3&uH=W%LlDhBfp6FUMY(wR1YSfU6BX2DVoz@Z;3MW$a4 zf`J0RL;eQwwfK)w+cae36TkOIVORID zuMM-we|nfr{eb%H-FEbV%p@_M~G)uvBjc$ zI!p8?Kh0Jv>Q|eWwkcqT#YIJ^551T3j~j}4U`TLzarQ@5rO+7XsW&2Bfx9Ym8cfJn;4df=Z9sP5|;*4wv zRF6Bl`N6iH>)7)5+9yJVqY-KxvEre1Z1cQO2!p6VR9!Kqs|OFJq;M7lXG>*2OwuzR zTw`u-xVdM1&xCg?>2K66)#G|5js=H4gs37`8E(gh>^s>fAp@pF>JYwMX! z)Xrr|;=p>gUTpbDa*F4kV-7VFAO*Jv1_PuKX91)W55cV?##`1+e2MOY`v;IqwgQk( zoB>csjLt>G=zJwH<{3$hdBzYA1t=zt0~kw;!Q+uG!&@9Ckl+Ehj@SlpJ#iku4aAoM z+$h>UmI{RD5f-aWy(U!~eAK5KNnd0CHMY9@*hCIb z8TMZj1bd7pY2VyyE{*n43WH^VcM?yE@!rmp}X>!cx@A_WG@O&4NES37uP(9iy!(a z`mGgie}o;MhxLDk_91acJ3bH&iQl%fX?a)TJz)N*2$%M;C-<>ui1C?H8e1faI#^oX z%09iT!)z+?>%(ly{;D`~n5T(JwahAZ{*uLBK~Dcdr+?reTd!33S5d zf|z&=Ibz}xVkf{jVoW@d7_T;o7)Mt|jJ2hL7*C>J197xd$#&q0AjTsw7jGzLjm9yICdM)T0-54(H+Tu@7{89#3Gg>!7r+t2rm{u(vN+X4Ts3;( zh`}e#Xyj;I&Bur_!75^0%;$*lg6|vpUShm3oe(}KbTW7b76#IBQO*#fzZDmf{IZB~ z0ON_VznmBsbGn3E5RJyIM#mk*xY|pJapZa(6kQ)$vc%~;DN6iz8=K3j#jNctLwOW^ z+(!A^EQ_WU+|AaCWBJlx*^i5{Tx%%H5YN8I9Af5OcuGE?R(*kFv|d6@9*f0nu3kd| z*ugi%QRQ;;lW`(`K65M4R-6J8dHG5@AE;L~H@jV|`3$eH1kc-KjLZ-pjN`H5)Mru( z-xn`Ny&=1~J3+*s!phZIZspzt(X;?lE=>@#ekCV~T??3%ueFI$6_zAX?v<=;gIK?V zU2eSDYA*%t{v$isr*7kwyO92m(&7KSi#T&E#+&`2NhRl6Dve3`JjOgnS-Oo+7@wHc z%pLxhDlG3z30=t-`fOR*YMGZ3p$vT6qV-1UA2RRnu@odm`W&`wOEne!)8=H9Jjd8> zpU{o8 z_Jw|{qS%L-R_MMe9ibdFzW;pQ&{|BIi}$_ZufCWqq48Q_HDxXmWlnlGM zkW`3oK5Z>03=`P=!EdG@oHHSz6=FKfFr(t#A~0F7>0BM%+$aK@ChwL)5$IZ{!Ug~# C#xhU< delta 184 zcmZ4Yl4;#brVXB~>?THrmIj9An*&&5gupa=-5e1-{FfK@0Nc5^{h zfCR)hpSG40h6!x`;5Snc&Y6(V3Nsy|*Qj{62uv1i7*|I(H;TZf$-AXc1iIF#umJ!W CF)~*G diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_hci.ar index ece6adf1fc5d801235c9b27e6d2988101e45182f..b05b1ab381687378a7ef8c0d1a74a1a78736a76d 100644 GIT binary patch delta 123 zcmezIg!RW0)(z}D?50L$#-;`aoB4QbwPBped^}>CGt8@Np#p{=flXVb)nWYU|H2r> jH(TD3%7%%6RBSJBXKd$(iEIa|3FL(F!16f>j66aBZuB7# delta 123 zcmezIg!RW0)(z}D>?THrmIj6voB4QbwPBped^}>CGt8@Np#qj5flXVb)nWYU|H2r> jH(TD3%7%%6RBSJBXKd$(iEIa|3FL(F!16f>j66aBbp;_T diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_sec.ar index a44c14e6593423372ea447f5789fba8a7c69a127..7e524be4f78899ec3d5fc786ba46305ecb48ff2d 100644 GIT binary patch delta 67 zcmaD-^`vS;FeAIEk(sfnf#KvnIkC+JjKKm(0^*w=3NGV;32g3@TgeaS*y*Y90|3s` B6KMbd delta 67 zcmaD-^`vS;FeAH(k)fr5q2=U0IkC+JjKKm(0^*w=3NGV;32g3@TgeaS*y*Y90|3xh B6L|mt diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_ARM_STD/libcordio_stack.ar index 1a0a0d2659d6f8447754b95874b60afe13a051eb..dfa0edbdf1472560c37ba1a0647f05474ce2edb8 100644 GIT binary patch delta 5525 zcmcIn3vg7`8UD{X_ujzfwb_L1LW0?3LmmXkLb7SX%Ou8-P$r{R9Cc9B3Xw-UWRO~H zEH`N}@^Cb=n!|vGh?S{jG$D&zN;?9TD#cD`)1t#v2#aNC6&s?Xv{GpLpS}02yOG); zaA&^x?)UxY{O3RC?m0Qxxg+DP7c+YI6Mg$fKqLaSK&}T)t^zVj=%a0TgWBn%uJpzf zppSm3Zb$+8D8JM79-O9if`BexzQXRUK)(s92Y`+q`d1q--wSlK*mM@?H9^1D1XtPr z!)l<>(51L+1BzhrO|i(lAJ|9~cLEcbwfUQ25%#m7%a>8}PX>WqKj>z%*Pa4)B^+u1 z_H}r_4A|A+-|fI+ppP`Z)Jn#WA%e*pL6N9P0_94Wp99L(LciJ$Binbq0m}cv{w`1i zem@Y46GuU@pv#vl^2H`lt^umY0TDD%Pz4tMHX3@gxbk~@4ye}yeUE@DF)#zvFm!zR ze8&xgHZ=*p7W)5dAmWSiOf0v7c0JIY4w{8|^5q&i&}`dX5a*jwR^szc_YVcq19MAy zCP;%1^{L|ni4DOb%b5{wa`Dk~o+!f^U|na&Nh2^6NJ-PojQmtQa|N=FoK2Qd?C%VC zj<=^vBhWkeMVb^wFC(|QrQ!zz#AT%AlGFLp62lvg1?1ZqmQ%vLE2ztO>>*N-EiEwy zsqj~pOuj9_0pd|h!&Crnm75rJtJzDv@({&puuD`=&pLzRIDD(yowRGfWS5FCU(CE7M14tZqs6w)PGG^FPB1xPncMu*Kc>P@7kGKU`Srt{pQy(W`D1 zQLj$O__{=weaM90!h#xqmyA@jJD~p zJ;sQKcQB#IDHa1yeb{GdF?k9a;8enK@wFV3fNE*+bsUt!kk#IdGdOK&vG@+E07sUO zgYv(x(~?vN=6H-B*hPx@Yxk&je({H@ePWGlg)CNgPPFEmo+G!Uh%qP*Y_~XppL&i= z(We63gpO?rz+%CZ0DdaC5MZm|0)Sr2KPWgC;61?}fRNxkfU_14A&U_{v-n?vCj(@P zIQGLKz%~uwdxBB)AukjI9To;AIx09H;A6p9$R)wpF&&ph4Coe&?eZ)RFEb7}8#OHg zs1%I4#`s$&d6XE820rv%nx3)@vttMROy;wcAHcBo zEUHVuz3WJh+JW&pp87oTkmLU09w%>jp4jOL$}4BmbpD7b{7=^Bk-7flbNRG$3~xT7 z<%DhQIv+$tNH4^GNiw z1n%l0dGt~OuS8aJ6Y=2UE4r}ZI{tJQ$sc(Aa3n^@K@av9 zDa0hik+8+mqG$)jy}RBrM3oN8_z!lG3wj3r=uz7y0?ZVQdV$6F3dRHD`&Rr9mj5Tg zX#gURhz|-DTM_fyTmUY?<8fCC#=rccAUXj6H+*=Ua=~~sG$HG@aR6(DkqWS1FeVBo z#zY~Zod6#R#)L`M0GU=|F*BNF9WywAX`&q_?i7sue`)pmjbJP!DA>v`3i1LN%U&hV z6948~oxD4aW$;!fbMfXjver1(LkQvT^^(Qp1fR7Vw@EX9U^i~0)r`AwE8@Nt8`C@1 zZ$Fnu*7ISEsUh5bc3#v+Jaj0Y-`0owtT6%LZhoLp@u>UowVbagS1_8uJIXN$@bi6` z)1JsfLc00Q0o+Ola3{L0?Q<%bcLYeGyj2-^8=Ev)DseY+8f<`Q-;$PLA4f08OU3aj z=QN74Xi<{B-Bwcu))w~q1aW3Q7hxC2MsuX>7Yp z=O#(Zz zvNmsQ=BysJ!y&EkU3B0OduP0KjNbQIeI)VTOY9$6GGvw>pQ(HrDc!U(ij*d4`ONya zS11?clzbf5#AyWPD{Jqxa{0moH*8nll$T(inX35LN{+l}Td7taRsJXoHv8RsQqd>M zOh)LU^0K`C`^@|H&pm3t{LG?@)9^Q_JLG-cXD-*BOVld4TxH_F1edX=UG+_|5|@bqkEBdGEpkC&$i{-pif!`eyC3G Fe*sxU2dDr5 delta 5561 zcmcIn4Nz3q6+Y*__f~;LRzQ|tSy;oL3M*g~u>{0_Eu+@XIITv;s!d5J!({TKL(7AV zCGjUQbw{tY@)I(qlV&Qbo8+aYW1C58t!7dT#+n)}vDS%V5i`a%I7-ib`|f6UwJAou zGauhQKlhyb?tAy_;m}KIuXLvQ4xrvK3Q)rT3gErK=??*i34OSZ_sLHm_D=852K3<{ z)qUB3KFs%YuamRHYapP@$t~;}1oll(T>)(P&~J5qGzr*nv1K-}yMlhV0q$`9g-&3h z(4}yr4j4g+ITVicgP=sB=o%;j<)42uET?rAbU7I|H`ai1@1O^Q?d=EUc6etmC|`$D zJ3zS;Tt5#=81zWRSF)P+HwdEOBB&B&kAZqS%zp;dJB5Cy3nKm7$AbF5aNs7W0!J#s zak>Ch3%Z=#mIn`kdKb{#k3$eOt3VT2lN|~@RJi@T7oa)E*s~W^v-wS=tE#2hALa$M=+veBRl@q4EHhYeQSoRN81_a zY1%J*R7l~cH)2MV*hb2{S;=;en{Z9WINC@pp?RG<|EI?W-oSPC?8Vg!=0EFufn1t5 zVKWwRWiysI$IcDpD(uDv;gdXHo&7xdEZB^hcIZv*6=qk1JBvTH8K>enqiZwn(UQ(k z@T!D$8?>LPEy}a(1)QDm1gqk8KgSta(-B~1Lc>?KS!CN9ozPGfQ*Hj`&D*e?x3w}C z_tmQDynhcH%lFo*W5uk}`}#xidKIGt)==TfP(_FgfKX2IDCt0QxSd7VS%h7QuqzRE zRW}`yf(g_J2hFsLLkJ8l!frF|;vfRU1`k>fFo6^bjD)O^2U6$(62fGi!Oh@eu|R># zVX_Jzhshco3X^THG(-kE!FiS}Hh{E&q7XZR9ma&pI>f?tYwv=P4*SzEISvko$v03IiLs>4}A1yvBHjFeXHH$1{>b6!A=fD^>vUTH=|?*Y~Me z{DWPZgP(nqx$sAPt5?b7gMF%f%xGHrZE}-C$kTbu6wLHKe9q3>w&S?b4l*)I9%SCL z9Vh680AtA#P3J^Yh@J?rMDPOu^@8&OHVMuH=&%G6Pbe_l2AbFd&#VqS8r-gsFll;W)wMS75Pu#FVg- zWHz2|qhONf8a+F3J@Um(m}RWkiGOCiCLQhG#-WjX+Aq<;=7P6=D9L;Nri1TFM~7+H zLK{?m~hbsx|qLI7AJ{y+d72Ua*@ooMgPCmLdVO4P zMK=!cms>Fx|HF?GF^J_?TQP@?jOFQVm=ooR1$cxqI(TNGl8HO{qivWQ<)9;R2(5SJ z{!Dc7w}sLZRCbZFlE<`@a#2t@M9NzJeNx)$NqH8yXStHCEr|oz!Mobg%|09LZR$_s zm)mia{1q{OyI9#|^JfHC8*@64vyx?0?(?YJD`vS@U@?_@u&E#A>4B1L>+Wd45if02 zkMEnI9@Bc`+?B?SPAsz}U7}5gRo|HjkF&LW;j4H=53LKLa-Il%5%gAiNG=WP5W?-u zw2SX4Fj$0LG3_FMU?}jrps%P?sKcHx1%vHjvI6c9Srn$I5Lpx^@sZ1cR44u_1!9B| zaFG1P67dkCZv4uU#irvK)lqIK#4bhMILx2ENQL3S*YKZuIsn}hh^8w(O)$v|E&iTh zC%}&_`}>w&e9X~f08U!=e!&^^htfo+03-`e1(+Z>A+Rr&20#VE%rjMRCcs)^J(`MF zqfjIQ91u)_%)k_=SIEf#7X?$mQC5OPjnYAnKyH0l-JRhgS&bAKFrmw(*1Msqx7Z0Sn_XLWV8Rwd7>RQxBAY%FcjCQk?kCe<7AAB#YgADq#aI4%3+z=zZG og;pa!oXLSGl@o1W7D_Lpa=Gnvtds(4%Ij?Xlcma_x3t6aUwV;4xc~qF diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_core.a index 3671aea768275c0a22b42b31cc8a567f80eb39e0..41afc866dd0dc00a83327ab2e1609e39d2d98642 100644 GIT binary patch delta 199 zcmcb!pYhIq#tG8wrbcGQrUnKZm9DbD*qi^c*mA%)lmD@ZZI0kw%!(o)A$%NF;E%+6 zxPG7(@y(oatGJM~h;P2AaS7Q_@y!Pf^EeSIe8o5WTBq?K1c26Fa93x832gr7yO0mY L0Xu3>i~=(NhK4+S delta 199 zcmcb!pYhIq#tG8wCPs!9mL^6Um9DZt*@m0{vDk9JIFtXeh;5GGUCfFiAR&AlRp5`r zd$@j}7V*uTa;vzIw1{uMsBsC|Q1Q(N4f8k=DtyH^`&y^*AOwKcUT{}ug9;dJ{^z@p N55@sIYEO&;GXSh}Jm3HT diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_hci.a index 949c4f0a4a6d9b4b8aae732459be8a377bfb7adf..f4a56abbbcb92fc66c2bc89c6e5bf0a55efbc0a8 100644 GIT binary patch delta 131 zcmew~o%z#r<_Xg5rbcGQrUr%^mEyUfY=g-k(#1B<<1UtfNlu6%hYlNX005C#DmDNB delta 131 zcmew~o%z#r<_Xg5CPs!9mL^6UmEyT!?8zU}#Wv65E|!1`OsEmxtgo`m878p#L;6e+ iIA=mlpaqNr*86WuJr`U6q<8jyE*7`|$n-;p4LAUy;3{_j diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_GCC_ARM/libcordio_sec.a index c10fdbab352bd15036234910c40b890960db5d1d..2c68aa94e0d04badaa35e27280cc56e0d43b58ef 100644 GIT binary patch delta 74 zcmccPe8+i$G`p#hnX##X;YKAq zJs9Zoe=viI)qC>+je!^t&Yc0oaB=ond|3_XZd_jih+$;#zJLw+5QI277|(U$5a5Rh zQ8vpR1bi>d_5uEXc&Y*LM6fys@K}g<3wPp|w*Xe~+cv-owk`*JFYLGuc)}3xr)X47 zrxx)4Lic*W486z4qOT0F0#UiR7hm28_yNG-DhT3-XMkhKFB=2#Zs9xe;yB0B3Z3K11_gHu6OPHRawA=}A+M$eK5M4A z44F&Ag2CFtUkXYf-P(?#U7wd+3lA!Xyi^%kyDMa@a(F}Gq=1qky^%n3Ok01d2`X~c zD?47glOrpp-7|v<>Fg6+&%L!%87jj+c)U9*I%xCE94xpN|82EFQCyvUE5p_P&oiRW z6u8VMGMZjUMYUv&uR;t5-_fmY(9~43tj3I6gqC(SgnoaH&`d?8s6e}2;8saIpK#R=)@o;(Q4JJ`Ot-mI~IyuZ-ilLKLn z+IHrnN{I7R6t!$CTET6avnf-AJ>0sPpcSX-9qhJ43|WA300}}}Ii%@4j!XfPfZahC z_80!Mmv8gE?~lK|bfO68&v$fl_4YP<`l23nb@orttQly3%$wx}ru7b7IHV#Y_MRnN^B8sRJRE4ZZNA`gcp~RLd!=ebKN3qy=EV? z&?JO=>`>=4W;SXPy_!8AmhUKn$+4cKdaDylh?Lg%+JHP;#J60nIjivGZg*{Z?DFNiHIDJ8XEB|EslmKChP>#FAZw*|}E$>Oo`iKkiY^7N!4 zQuSjkQ4QtmJE$85H9SW72w60gsUMORt*l%ojYC&a4vA?@AqT#$l4?shqqOidWRx08 zI29RK5SR29nvN)@P?#YE&Qex>MtX5kI$Xj<>)53k48W6v*A9^LA81I`H*bq^R1HZ1 zC}V5`sAHT8@FwHQ00$Ur=*%eNcz^^J+W{Pm(*Ra5ru9vX=@Ob5rvtphnAY_&rhbsx2qcT zbRRVPqU9s3PFU_yHJ@@ClZ>KGRv^{V)9&PGYrE=Anxv2Qj{Sw^o?Mtj+aiIs#ox=} z@mN}u1V#}NybE@Mop0`#3u5YH9=^q#oA7mPmstxg}h*C6L!u9$(A6LVI*p=D;OrJmEI{qN-VCHEl;Wrs-&x zA?xYjUj(^v&fto>y_`b>S=)`eS+*h2@bc}8$y$41)K?~jF*QMd)#5-}s*Ql1# zR47k+NrjI3&$tO-D$NZs1Jp7O51j1?fDc$43GffbQ2+y!adhCU)4B|%(>l3FVgPDb z91F0QF|BW9YyoIzOnn9!Q-3xudcOh^*abCqP{#DYhq46PNz_v=U}v7)&taShu#hn| zc$zVtKy`qRF{X9L8CwB9V@xM-E1-uWa_Drv`x!NgLTHenFYJ6AZI&GA4;o}ARXbHu zmj)%HCDP{_l!A&Sla|r}=?O+Fq?L>=uoJG1P|?|A=}<4W@yYafUn8a+b`&Zh9lCSA z*$dY_PlskjDo5T;-=3#X23+XwC`A>fV3urC@Ede2N|D@DnirwG zDtk(z-DP{xlUa&zazt>S_M){qMPM1l=g~5aBCw1PFQO>zXkp|_)H$Z)lk4bZUddSW zmf(K=7Mf`sB}lKAqI9>GNi*7>BHF3iGQY7l#|zy z;QqE7rzu4&M{pN>gkMv(!Cy7lhlj(ID&}+S3w$g+U)j5ui;h;RWFPMu&M-w$&? zdeQ1sDq8WVS0K%3upJ!Z46-K6bXrSBJCjUox@)pFwG4rb3F*{0n3_rzNzd8cyWtYs zfYCei@!kLXALl=J?|<0YqvtKx&RY)Hjrmh^3!coMb|#|%DJ=kZBS2;e9ta#80gV*O zNCO{IoHF80A5H_x$RE{1X+RmpXZ0W(Sk?-NLD6o8^UCFb?gu}$02&39Zw2qY3TUJ_ zmJjIrfqwqqufXW?Lx%wAphSg_Wk3v{9o6IdML@&R-vWqXaK?QBCmwnt{yGwUyNb&so$&dyw`@ZM$#-|{kvN@jW=ruHO|b66lFzz(fl(7^ zQOUQh?q{)xuwXqpJtm+*8nL?h$k0_p-*~?$4yhsf7QX*tq9%k>LY>d(Quw_5srd(A zaie2ob>AAL@6A*=Shc1q88=D0TbtTYy^+2@5&-%7*5KE?LrHk5PGe-HtDIi+LDc~4}Hb1AUc}lscDPkObDzgoe1_lWfk0x(jA2gYUDPUauYnv z8!t~+;^w013ri$vXC)|;%mG)P1nIz>sM}Y3<&x0a_lJo6pWcpApjY3UKi|Bs)tOZu zjDJknJgahzx6_n16f&X$}p0@O)xaYwJepGZgflz8XF8v zb)_q3j|2ObMO*CH%rBFIn-6YTCMn5=CTaarQf&VK1t&ZzWsMS8X?539YF0RgSB<+$%ILDfvQbsp#ot zyANL(!rW(9G_D|fzI1uwov5Is1kdS^W>t90B9ExV5iggQpt)}^^p>#%&F(1omiYof zHzM9SCK7+MDB%S4Vlcp?l#h`!>$6g4&^tuI{$MbLJ^duOK8swq`3}k^`@T}qX_C7# zNB!_6WFf8FE!Hd1lx)h$5C^^LaUW-!z^bH#rFg*9V74V}CqgRu&A;DJ?L4ip=+-G^ z9F^lT0VXka11w;i0q`>8i2!>TQ|D2}M%pT6JOMyvwiBR$aaJ^*)_INDbWgu!OxtQ_ zO!GP!(|Y}sS^fay$&d+BR2a`VDN>j^z{Tt_0JJB-Iljhz14gfsk?z|T zwPqpaQ33htwi9{C{J)FDbH`%lO#pLfQmWe1hSLNO2FMO))ZDS4d8GbMrdo6s^Xj3q zIE4i6Sk#Kem?u~7xR96JxF`~Nz=F1t+<{C~6Slq7-bHo{WC{mjr8=l~fCOobh1CB! zGhsFd;Gq~x*Ucd7*4l-Q2HHBQU+YA5WZm6K+F8KP6Ru!d0iArMlQv2(AwNuRNP04`I}6;w=4vI&{L$;x+|1K$&9zoz zTSWZ{)sxmZ#(^y zOlOD`fq-}^Skw9e;@Qxw`6?VbfV z7}LTY%4}%jSwI@w8D*NlW`y|*7|Q_j7}EyJ8Pg4Hj`CZKY2NP{r$-y6^#`MRJgZL| zhbbGj{KOv;&|E||?sN%r=-?Kqvx3-30`CgyIwNuld#F~f=I+8a^$jDkuvrq+x0$D# zdMeZ%%rihe=w&sx5R0nIMDMS$F%e{*&bRu!2|0<}%p)N@A4TeE6B;@oqW`7|{UB8v zne=m5^e=Rvw3#}kZW;Pj?Ef~4QN4*c+rMfhT4U7(UfYQLV|7Z$UX+)jQ!K|&$>Tc3 z8$z#`b;>{&TBcjjzwt99nshNO*U=yKS-bktCP5b?4WdGePN9vf`kq}f{;ORVBhA47 z9J-d|Pk$QkjD5!lKctQ&c(1-rVm`q;QoTtGUE%O$t{z zeVChO(-bvPrklhkxoxqZ&B)qf(f{iU-1KqLplSZDF78q7xlE%w9_yDs<^GkX`B@Rs KpDXY$j{h(1Tj+cM diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_core.a index 4e612ea5b6de28723bf2bcccb63416ac0c96590a..2e55364a774075d78b2b554f4662875a1e02644d 100644 GIT binary patch delta 196 zcmbRDn`z!}rU}yQrbcGQrUsUi1#HDOTI^?m^35j&ifg3hXoR=7Fi$EMWUm7{=KY7!GGo3Y6Gfmck3;gX|XHys-R~7*sLXF`GO31Yu@d QZeB23UJ6C_&elWh0Cl}JumAu6 delta 196 zcmbRDn`z!}rU}yQCPs!9mZm0?1#HDOTI^?m@{J}1if60k#bC=i`UGKS8*g4P RTV4t(3wG+}J6jL20|0@ZHO~M5 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_hci.a index 18d077db45e1447cdb1b155826804fbe637b96c2..3bd78bfb7dd2383e3c72651cb67322aacb927fb6 100644 GIT binary patch delta 149 zcmex#gZ0x5)(O(=rbcGQriRAT^K2N!Hd=UcLj?@L0-NV?^J+px3?U*XOo~fUMIu(6 qRfUQeLDV>1P|bmfYzG>ASP;eo%WwDdV-$p01lA(Hy*85Zs}KO3!zso9 delta 149 zcmex#gZ0x5)(O(=CPs!9mZs*@^K2N!Hd=UcLj_F10-NV?^J=1soG>Xag^HL#)I_X0 ptBPXGW~U3PIWUp!K!Xnp!gydE+x`3)1z{F}Z5H2N8_D=p2mrS#DkJ~^ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_sec.a index cdf8c53015f9e739486008f4850fab7d03fe61ce..414d03b69eabcbb67c4cb4994e015bc174b9def4 100644 GIT binary patch delta 87 zcmaFS&G@35ae_3vsgaqnsiDc_3kqTrE&fBf#vtzI5XSuiC;|pTGx=Zwn=dG^iXiLW J{K@2-006Jg8vpf^=0J!=aIsgCw diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M0P/TOOLCHAIN_IAR/libcordio_stack.a index 59ac1273caffdaac5165428e54484e35d2281062..197618e7d24abcdeda8bb54d5758ac4152e2cc05 100644 GIT binary patch delta 6009 zcmcIo4RBP|6+ZXApJYQwcG-|!NJw@UNCKv0vzvqvm_n?C@E0IeQN*$$>f*E{U<4%S zBcLeEh`_eoAfSLh1I3OD5nr`xi9n#1)>ZLm@F!?HPBjdmMYJuNp7ZwYb~kDTgf}_+ z-SgdZ&b{xvd(V3}Yddm|9?V&rlTz-h@R$32A}kcg?h(tG762AD<mmqJdS1a`in zov-0#veV9crk7^|+WDvIvP?j`fM<0HC%^~%9t_c9jhK(uce-^qcW zuWV=q{^LaZu>mg3|C21>Nurs=*ZY8@NEzN_aUTJxr&PQL63JNK#mSspkYb|68t02E z&VY0YMKgkhuL9}20>-$loRP86aP< zXcyy@;Irc_$loUimxE05c15yutp+(JTCDLMs95H~j}reGP+}734+_b`tx2NwB)+AK z8K7JWdAS3Wn4G#5l&EN+s?S~?sd@+09~A8ejBfh~RFcIRmqwmi0&1dMnW$V`J2bj# zMcb*gM+)N~H;rND2<`ICj1r|~;&_+rXdCSRMV`r&)Ax_FZTqyo#c{@!!Lr+q-u>Vp zlc^Am0mad#Z9kr!%-sFllD=_fYaT}K`|4A+ID=l!w&Ta!vsL3;t8|^)(e~1pHzcTf zMFz`so87|gksSK$64q6a#N2)@`ywaC%s+rOOBXO{Py*wW$}9b$WzQAy&aAfd4?Qe& zx;|?|E0f*N0|186R`EORaqosY#^J}(mX*O`)2n9X;Y4t!(Ml$SJ{Jb#i+>s=CuX>D=Q3~*Gd~L znuU#VS}R+EFhq`&LU%3o@Z;D*RKtxgwk#ev1R{;&PVc=x++D{Wu&9>aO-}2mCxWS- z>Y%cN>{30!RYRQOPmiQV(^u*<4cmgN} z1-L7qgm?_+BP;+YCoGI^8}c7XI{N>Va2UX7LL74pAv%pE#HCk*-~lhdL?Y|}lL$)z zrV;i9s3$B5RsV9B7_eAM&!&A^ZNKYY`95hSU&E^H3;7KDQZfHJX_T0?hNWkpK!dUN z=6jX<hDj4|5L0)s4PwBn+#)`mt_~NCoh)5Uj-Yz$E&ONE*8Mx#jg$+#El9&3 zoE7wP0928ViMWao?{$KS^9b=Cmm>D+2k-*v=>HKR=HO$K|2JWOfOEuSj%D1vX)1sd zk^G8D$MLEVwKPmtkO&O?2pQx6giYK>JO+N95GQhs5R*>jfdYPoNCB~sK`(rwoDlt0 z!T|uOgn76}3DGXsL@EcQmvMYld?-FeB)AMP%EU2*S6~JRaTU}OO8Brg>|)uX?=Ci% zWs16W3MR5nF0y#B3;$rC@aFOy^=gc?nTv;x${v1N4K;2q;P0mk+c;jJe4dVjh1ijS zMr&$l+g`hv)h<~@>p|ueQ;%`0*hj6Wi8ESTiL-VvnN7zvZx`Lz!?uJPz9{4;GR3r7 z40;aN+38UAUj`~CtN?X}*=cm+RW`BvWvPHo5W72=Lm1q{Ho^8I_gm5Oo@8<#+r%{D z&L(iaK4RN`DO)Ui4+C9^3Xa6?5mTOKg?x>vz9Jq)l^qk?4q^Dt{gPEJ#3fzHLe+PB z*et<1afFfslGWdk1weZj^9cB0j4Ks?({5^Nx?|R&1#_Ej8P-tZa=A*&ea0)%=QUof ze8lij%l09xRc{Nk^^CQOnN2LG{4ly6p;*SHLIg2Ue*^VMLjSv{9~B$+;JfLlcy6*WmNeddQhxulX3=A*NPrp4<+dIPT3IZ{#(A-dp)y?+ZHlw)muIK zKS2FWoYPjc?Sm!dpQvv{DMKNh7VB@YPiA8NA~sztc!s?z3h!bW`t5t!<0)A)B3;eF znwM8u-7d{2sPOaG^okeR9xkPLCE;3)D^uRb!WwP>Tx9?*qmTiB8Ntd4on{rp9X}FP;csWQ00yJ- zLBYlmVz635d|i$w#PU){h}$Ms`K~4%%g=N|oZ$>YoZ*dxxQhdX824sEv2LhZ5-osK zUaET*Ku!O;ow*ouiM;*HK{A=+hOu4n>fgxEid5c5<^h*EFz*AZeK=Mmz>fpIbN0NW^X z{ZcCHYt$$)#xKd-5iL^qqHrI?eY{ekw)vF;wHEiFlZo9`s)q%{XK2TQ zqTgXQH2P7E^@2Xm^}u2FenFg~FL-_CDYk1^oHDEiOf&xLskCtqxSko!bFF|y#Z>P;h`QLglsPxzWFlkyAt@YjFx4X?K*Q(H2md+gD# zbf0Lzvw%LrBYplqKVy!y!=(`!F{92d*{MG|RytyyPJCr_yAFNT9O?P|n98H=W zS1L6RENDc>6Mc7Bdfsl%04Y59=&KG$uk<&m@@S~}ozlYmWJ>9lejTTDyc@T9gz;5G z@2#^$o)fz_le%e)e9mUh2#+=Tl6v{i*Cyz*cghX93Hr%{vWVH!Imf9#_O@J+6}uue0d7|zwH{NVr74acR6 O)yXkOpN`a+ivI!?OS^jj delta 5948 zcmcIo4^&iD8vpKnfA}jiFgP=XzziUQa%2!>1S>%W1)+p3>r@t%6>Y9knYvK>z->#; zNmEC;+Pa389W7LZr8(7FYUa9byJAsxYD+k$_EffN9=HFtk|EhA|WhqT+W07uUGW$RUA7DmN0D=uyzv%JismnPK*Y2uF%fa z@DkZ+=RDF&GXU+}Q*}uOpqM@TVqLy-~=(olGvAQ4LDT^Q!v08#*2pmDDJhzF#L z2u%;x-U!m!un$N2|8TSjr1Qa<9*{zz4OI-va?+zPi0thk2T3AU5HbV z&(?7u{}f(-1!TgJ`$KVTKga=SfyP-_iFgiv5%N5s1W+>z6vD!Pg+Lps_>nAHK)D!r zje`=viA|sw&_GpBT^dY`2lZ#6{ftp<5~zg5FRq zINXTj80PRjH*U6Z*co3StXpMA=g8b!k_?M{aX67XI$Nt8Ss{v^hnJ;=D1Nu8&mK^G zQK&jPA9}H2c!(nY(6-nR#fQDG1zc9T9i6XybyJY&&yQgiw`q^v{@b(Jv2j%6gEc6e@PF|n`y&&!TwW*+t!InH zvfna`$ezs<|BOGejjDF4Ye~Bb4p?0OVtoXk>Z~ojr!=D3QotJ7*4B=Jug(l8a8>uQ zhD{w-w?`uxGV%{^ZJ4g+zP+V6A`GpU@}8#2yn9UV(#e@`)s{lD#nWhdy1VDqWHq5~ zX>F57%Xpx+ls6YZcuock^H8jTspTH67{Z;6V0A`MXsU%wr8^Vnn5K90-b^4fsr}@x zrp2k5&|Np}WY=Tu16Q-9f9oiRDrYk+a7K$=&#EJHDz3KLW=>ug4YUqFXoVsZPtka2y z=_dGK0kTO(|8c~r0ON_#cmgpRPb9`TR}o{JVx%i!EWl(^SOBIFqxW=T990>y2jFUA z8^AThIRMuZ4+pqTyfTUBilQkz+IM3~qF56rdv(cv8VyQp4UZ^)kRO#E+} zF;1qD7?biGF*?6NjFas~j>3$7MlvSz6fq`A#qCJ?BxJfz7BS}HMr4fwt{{WU0XCUT z`1!R`PUK*0K#P%PitBO2j9RDZ@p~Djv(8_RatAD0WJ;qJ_e(IAve)KT`R(R#Cj2 zrStMwv1b)VxKR{sXQM>fUO7wnwzD+;WvsZ(hr!f1u@Vh^b(PWLWgj2Gs|^KT9w*pp zG}vIu@5PC#)!Z&#-NCHvGts?+jZ(e19y6G)_~8_OYrM#gQ0!uU3%4rs;sI*KeIIb! zWw$L@@W8E$?!RZjonz-`yIiiE@#FOOW4_pVMsi5`o;+XErcCyse^)zO#aNq|*};-? zdNIw$rRs|(SbhsTJ__o8ALUO(E4r~y#O@AuQ_e(u%7Ke&aOn`adWbw*Y)O-n*&;Ew zlO?-X4e8wwBvX~x?6Z87AZC2da0N6mV>BLtP$%WCzM? zu+PcFeT&%jV(y>W`{I_HnZ-Y?i*UQaco5AeETN?0i_O>Bo#t&Ou z*Y)~`?P49As@Mqe?yIa_!}X2J2f(ctB*2#q#E^{pL$7LBEO5!|f?n0|pI+5)KctY} zWmYxx$1SESaVr46RsnZ_-lo$olT7KYKU>9cM!V(?jm-JoaL<0>10?!ht{}e zTZ5>3Q@%nxxeRNYZ7+LA!(mjTS5y?h9FyyjBQXbmA;$iH65}vGB*t8g#n6#>`yyf- z-VMm)|7(-$Nss=|5W4{0C3XXRZpu`1C|(AqVunegqeK+GDvFRJF?p+rF~E9aELP7F z;|&j*`uB+O#-IDqNI*gumP^LVoa2@r|GU1rBz zVodZBVwd>#HMW7*aWSSxPEnpfUAj@Hx)jm30xQ7gD6um~O;=vR$uAW%=do0Aq>VX! zyDO|>02^Y`IMrzRtd&-!6klR@VnuN--sfT5W!1jE7gG75Sg{f{{AjG$p(^P-Gfwp7s&-#Yuay_XiJX2M z-J@|LcA;YTxvH%ES(`XiCELZ0LeLKkgb-(QlUik1Mz*V^F1At}bzgs#LA8Hisl?npmoM0T7#nEU3$qjsM1gS75k*WUv7-StAD8Y^Nvc3 zl0!5H&PZ!QHT6kyl=&rMdTq*<@3e+^r4`BjgEl)`xYIwWT0S_-w4v{j^sVyz5kYdt z>#_)VQ2$*=WUrYGulc?5@-caTqA>$h>5u5C2&Hy(unMQ1r-YePM=O2mGisDtyJ@9= z)j0fz7b@$`$L-BCa`w1TD#rw@{1|?n`OW6lUt|836H2ZlFiU-@{aaO)JkulJ2ogC_ mJr=mTzOwB8xLVa>K79N&yjxYB{-VWdWx&x?wY8}k`Tqm8;&T50 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_core.ar index 50cef239880453e96fcadd172224e9a76621b020..37bf058e0e6fc8b56483333b79c4192a620c948a 100644 GIT binary patch delta 180 zcmaFzlLv?THrmIj6R^8yRQ1{en-yW_SxOknec2f0}= e4oG%;lsDsfewfI1gJ{M?P8bg?zb=K*MhF1By(X9d delta 119 zcmaF$mi5(J)(scA*-eZLEe#A!CoixN+x(7uwGK>R^8yRQ1{en-yW_SxRKRTWg$KD= fFb+s|dz3fhd48D4c7tffL{1nFEWa*=(MAXWyv-(@ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_ARM_STD/libcordio_sec.ar index f49279aa10687d172740ace5d0e057a5d739bd5b..c123c98a53060a1837b23f992f124d29b0ec24b9 100644 GIT binary patch delta 71 zcmbPIIi+%gIU~ENk(sfnf#GI5#)Et?&SX1A@y)UV*La`;MnD0v%>uH_0!RYln+O#N*3I?knwwfR!kB9^xozhGulBBiNu~Ac|@sXJ; z(Zt7O3}&7Fri~F>YH(^S(de~CL_3*`i7#wy$HvAH>U2mkc9&AR5)*s=yZ0`8H#Wi7 z&V2XW^PO|P|NQ^mb9dXiQ#-p-+ukLL2gq(6?U_LC1$t0#xKM_hc%Sl=VRw3e8c>FR zRQII;{`~KY@Ym~7?*h=E7&p;&{1Tvdg6eHRZv)C#lAkLAI$Uf!2K4Tr+^xXv)dyRF znxKRT!FC8Vq!xh?iQE`3doTtiFEGle*Y5dud?NWZx>D~$Y)P36y5tXC-tV7 zh}`P4xh5iMwQH=2sAyh0%0%=WWQiu?^^*_VO+@hG6t{_}`uC4V8pOl_(XDn`NNT!? zv5X@p!@Xiok{XytCU{Ia)0UEdnX071{Gy^X-^A*yniEdoA8E2?vLOvd1Fa;zV6O?< zZOh6zEzB0sFAmx~5EOGm9DRgpoZS=hr3y$VPtSOoo!UaOl=2N_Qd!NaEvweGK`%-3 z4z3w&4I}{C>+UkTyQb{sf4{s5*~uL*takc~6U4Um9{>6rWm>h|OI-8$LOIDD$5%W2 zO?u4XPfL(HT|p5eVn-<7>9-`T*_hYaIBT8GK!*iaS+nnZTwVkt@keznK}&N>(At!( zr2VXBDw6ik9;>hv^HeZjxB(; zGnwgXpv$bTRVA^D*vVg##lEH|GTG%un#MX7h?%VIW2yAj&qZJ64_rzG9qLGgz|C0^ zJ^+Cd^ljl30_Hf?;`VTyM#Y7wdLb$Ma5+;&W|AUkzu;N zfg&UXu;3#xV%#T?V)9)SBoiUP06SeEc$L#(O$ z4tj^$!2EbPXYv!^kjb|yu){>eLN^L>O@0{IHJsIbzIlobj>CQMIDcABO2DK0{OLF; zg%PH>071Q;AHI`{z|a~WCuP6*jT|pIvF3U9NuiL+nh%gf7EC5~*0e>kv%ft>Yz_y8 zryDhB9lrJ+FKfCfWXI8X0KPJ}HWsskR69As&7T5WZThzaVb`}@-2Pd+yH7-72IN8wQjY;#f2V6pNCG(tO*E~n zlAAWR9F24#4xpB8e-qR4*>PlInsGz?+1PzE4tO!m(Td_Xt_l|1$QEQe*^`{9`b=ZG z4tV4IMg>+SFw#y^B}f41X6fxDL+Zxc?Y`r4GKj+FI%PL2-c4MQKV?!ueqrc`i=MZu zZ|o+2q0Y&je_x%gl$6=i`RiDK+;i;pJ*1e7VV~?Fif_@S0kvi?`JG4yfqk)$xJe}& zxu4ury6_B*4}W1@itzaWTtt6pRtcEnREw8|YiLwl(Bgx}0yz2ag>$v{hXQYz2nyRx zz5t04K7UaRiG^MiU14$V%W%TvkAU~Fo=fme@Hzgy?(?Rd6i04{PHM+1C^TlA}R`xv)4gsh5pGc3TeV_fE(OL!3p{T({y1zbkrNQ0TkY&>m1Q_ zF6i}sZm}V*#~UgFP#;vuR>C|R@oTd5jIh~PcU4s1`U8;(vz!)jJ}-#u#9>lHKpVf@ zcX2#VFvn8rW()ZJDYm6fa{K(x+NJS0gbms_?!dbx+FdM;8Xrs->&I-V0bM(bIf5g# zj^!P}A?vsCA=}v{W=K^yZ$+#TgTAW)3+wL^)5unK8nb-U`Yf!p8~u0K=yt4{k7G4O z8=OtPod;9c`gRijYpMNle5ajU92YrB>Yg5wI>p3X@zT#@P0Wq)G$F&pWIsyRW{(K{ zHJ;3lRtawPgXietbc6E6Pa37xyhcwhG#GYmP;#qNuhTwPm^$O7ZnZK_cq%?jjmhIu zsY12Gpj4zbhHKQl#X^iN9K)3>!;7l%&j^1V@~*uiR89Zj}FXTo2!xs`IV`tuI?@WlTCz!yP* delta 5776 zcmcIn4^ULc8UJ?Qz9%AhcN};ppxpIPP*H?v1gjBH5ey(nO?7N4)M+d_{%h-msF`_E ziGMm75_3$~wA#po_-ASig8EWLk&ZgHF-jHNnkE)(I>n$4SZfJQwBNpa@4P#c2LHX8 z-}~+N`*y$mcHi55`&!!L>MqCC9VTiPklhB3R04Sv=y(}OU!nH3;$y0(_BqqXlYrXy zsd_94sQ2-#9$^ABVL#|l%|a-TIt}zeP}BqTKA_%HxqJ)IzT!<6(1(NiumSF`{pVpo zgP{5ZDbfi#;Y4Y78HRE?>`zeO#>wmIf2H5l^d3X|0-D-m!6h6HjTTZ6h}ki6P>aBe8L2N z^o;Cm7*q6Nim7-9J~61lxyC-s6nIsy>}bf}{jwhx}N`W0;D zZ0P;#ct@b(Xej*G!Wh3Yzd&+o=fcQfw_ked2ytrRBgyZR4Jkt;q;)+@QsYg9SE=$~ zZOU?T)odp!IapfyIF~oAC~5B1C=i!CPN!sW!4Q!0p%YJXook`ECn93S4B?Vy3XP(c z)e{zfuNGlwavr#|7gQ|Z$2XHCb?U}kIk$NA=GE)!pp&=~de?rwtJ?zW>m9jtcV6zD z|J=UAfHg^VM>@LJ{e4ZcIy2Ym7Ahpi8|wBo)~+mzS;yKHX4$@JOw0P5O2ZFLVHk03 zeQ>N7N^5(dA9Jg=HWPxJXQ^t4_2-KXeNr{5}G@{Djct(Y?^{Y4$AAnN9ln z`cbf-g7tNLqL=)fjOHi2B>*}0Rh9i-QP#^F z*hXm+ts>LyFU|_LugV#auivNZ_Zb1o_x18r{a)(x+E?+-&ne^ihjVDe&{B+=YhPWd zydtk>8>EdG^J)7^x;WgvI%hx`Kl@9vn3v3EiF|DZb@@v}`IP7BWOXjRn;(PjJI@8! z00f>z+v=}EAlOes{4~Tbh4`fqKU4JzgZv$^kP5Qy7xU)3WH zK^SBN3`oKOjSR9?3Nb-~1WJ(2pvxaz1eD>EAX|ai0XEo#q9}u%Jn{fZ<;5qd%eDwL^NPZH^Z1ePNpUeYEEbwNvalz4_jQco zSv#aeo9LPj^rfIP|MJ%)MI8h1E%b!rRAmSr4X{k`Fn~7%j{v9>oD6Wz&@T&41n3p) zLEy;3hht=e>x5z5O-`hysT6qm=r+j<29L<;15-V>jkr_W;sYLTG ziCD?=ytz_w@J4iz75vAOn8Ul|x>eqaDJ1gEhlqz4Gs4Ic?tX{N;^W$AG_QPzOd_xH z=96+F>yN#8$xIKa;5Ex>5;@_c{=EBXl0*sxIr!Ec#41;ZPT*1t*wir$`?878c+2HWzxx+q~O`qu(Az)kM3bkqh;K`d@okY{!XL#~WvxYNNmhMdo3JK} zC#8ii*h8|&5dQWaqI%0N-PD|W$!}P!ct!5neRFZAoXtO}CwJ7qg)X+jYgqs8Mc^~E zr};Gk!G5aybNzlA;+J&4$ia6>aNb`Q8w*jPF-V}WC&-q-6JU#-rhkAfcA73THZlPP z{v2fYg9}(+G!cUk8^KY-7D-1@JB7W5AhHx2!6`odwv@oX*iZhU#slEn58*=rCJIKo zz~Fg;9RMp0f2*N?Bsd13O)&az2p$5UVEFLCxb_9dVm!fiUtTm0KKrpLNvf>BapskF_0eE3Gju`G2j@ZgGol>2M`7DJ0qUH$zZ(eMjSm+ zObq8k0ve}%bdbDB_`HQ=F1MVKs=TFFnO5{$q7c6GG_!eM{|n<~he$Dr_S#O_`RPNr zyg%mqmQe@4Davg;tyFe+k6pBhCA?BBVYvZIOGJrV&oV~Dy0-J`!?<=g;@Wlb-G_?8JpSmuI&#kGuklS=`-7JhU#7SGBX@mNlI<#%0=s=HO z(vPrzD54eS5jN9TYf(8}Y#vxMeW%(j^n((kU8cUywTnIUhTSh=Uk>d`gtTCwUlJ#6 zZBd+5WHTiVrA_`eT2YqN-^?#l!~F97ooaiRN*4_)eXLgXnv|dBi-OjrW704qO8QuF zp4Qy0(v!xY0{Z7)m)vICG-KQrb}PXMkjC|7_ocENOR!{{!s?Cu)6=+~e|sT|wfTNZ z(!FGjLvxm}b#nrR_YbnE@qvQ#Jo}Nw5P0_pd@Nfpvs8PK((!LLW2mV-Q;u_25G{Xa zM3B-rS^nopQ)%v@POZ62J~_x#NC|UjwW{3dHWmD5a%%6^$l;@dlnZC%`cVN2w(6D3 zjlZ4r30!}3GNY9GCym*dz;V9u-zHxv9BW7!+Wb{Yq&YVkzBZdSD9enuEj?4aeN;J@ F_CEkWZ0-O6 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_GCC_ARM/libcordio_core.a index 4fc8c40353562e51c807a9352869db471a808a29..4ea97f8da9e2fd0703a73384b4df532de515ff91 100644 GIT binary patch delta 195 zcmdn7mvP5l#tG8wrbcGQrUr%^m9DbD*qi^cEM%sgaqnse#c(rFd>A+i-IS_g8V4#O4-dO9wdTNb*_{IH#iGuNj%iIJg&rHS!IrFd=_dvgc(S8+I}McL8;&N-62Rs_zesQ7CJ=hUoU S$OY%9?2=`Hb3FEWaR30{Rv)9sa$y_h&h|V>#5j6OiSw9xCbyYOfMgL9!%j9F5b|kk(No4NkQ+iWVfg z5J=-i>HsfwH9CnJr~a)Yp7nGZYsT1WQ*Ajb6Jw3ViH#(f_Pd1Lr9-lMLJ-*4g0m(lB=!^jI+u(s9wF6LZA@?@$ zA;rnPuJqv)AoqT$9!ddnAD-2NEZ|uWAO=}$+{wk40o@DAS^@O|^0$K5YzEX@ym=hZ z{eeFJ`!ncU{@GeUJs@`p7vljj{D<~q@!2UrcjDGQKn$JJ?g`jj3sK0io!+$5G66q8 z$g0_dlYsAr$*q9@AD*fL+!vHg0^AewokDkic{yMWE4KmGP+J1{Zdelr+-J!5k`$Bk z_9npp3-84PW(d$($KpKA*C1<+yKx&2_&&fPfGDzN1IO^_wH}b~6u#A;Q3l+D!1FtR z(?FVmi$Df$yZCT$Y#VUj3HdvME?fnU;UnRJK*#Bz2lDR}`rh{~G;Pf6`kN-(XUX}( zqIHzD+c}#rJ%56|OUY3zb;#~pQS?btRM{KAHedBGwwih>c@#tl8V-z&K#w6k9N=GNEWKxS@pb>%dJrzKY& z{3OcNw{b~DrLX#qRa%4f2_u^u4X7o#a;k4T?L(UJ%H&&Pma2r=F?|$a>{M3J<>|HbUJ4G)usgiay zy;P|S37j>E6U1iyhCn#J{%{Bq1~sR9#mduRz6z1~-ZM@hxzfo(QC+P8k>VxZ2bGa2 zF|Rl_jhaS-vBfgw#|vCdPH$YgSb3=M@|9w*Lpm4MjR6+6K5TI(8}pAAd(VY=_n@kl zE8_}w%x#U%oUH&j^-~AUFPcv#T_57+rXmkVmo0BDUb?stjX|xsvr{Dm_ZhPu~<1bn-i3} zOGrR|;+>kNY&wSdA7s%GE12MY%Gyt$jgKklTN3(HSRo#+clFtr6)d19i@w}LhTZbX zbEsl+0<2)139y#&Fn~808)x{|KFFhpO3c3;3Fm48J`TdC1J$F7ybgpw|+zMZNx&Udu^{UKbKahf8@p71_z` z4gr;s1syK^dJN!UK1%Beq$7Je;+6F*qPas*-bqDSNF?UY4E;g_fL+N;!x{P)dAh`8 z%mw>^UoBZs_S~pnjuu66%((2xKVmrwdv|c2?8resKu&jN$W@YA5+(gko75QQ>)Ea| zNRTHyeFYdi^}E|Q!ZOlMn2!0MXK6#{(J+nBKjOcd31+n(j(|mRvJ+TvMXDR z$fdNN#5(1a5e-2z6#9O4p+ky;r?gPXV|0y#{@^l;I{F;waWK=n2&7?6vffR1{g-6R z3rR#Q5~$ZD9u4pQ+|du9e^?xvFd!F>w8KWks z5g(%we5^3zb95pm#qJ*$MyvF(5zU<_S%?*Q3w|Z0Qk#EI8m>u>jhL2;Z%6NP>9oWD zvjSXgiH*?B!f*BPI9`I2ty%<|T<3CZiI&cUVXN>~LwAJ3|7k5=rbQ@YHY2-#WgY&t zyDLOVjH6309>KHBnxe)uyoU!yvqEQS)}I6Tb!`chne&;?zwq@0EsOft{l96$=Lcwt z>hm(RRMB*$?T!H>Hr*$pa{ruYu87bsM!W267q22wq5rj5DjaCKs0PP0_09;eFVs;A>U2VkeK7W zK>iobQ~}}evsDkpc^0oh)^6^^Jx>6+2MG8J2qX6$5I7#569IX+@IAZiGzepXrw2gL zuq_LO5M&VET6KT$eh`Eog!}_e7as(HK;wZ>R7ZPhm2SPXezrVc5>^@mMvTtqBOcj2e{On|1NsF=Q*EZSpq&J= zWZ*-1*;{h)oUs4TS9+Vc{Y^KpPu{pF5vqG0+g_6T zH!S$7T-WAkHt-|{X%}q|q{&1WNB}HihqKv~>1cSb^m2D~bFx%l%RP@Zq!>z0RyQB39pBj54gLB> zZB?JC3(VrHuGh56~Zs!8*=gi_h z<;?Q+G3N2XK_1|o2X3$r3aOkep$XUk@U14}09b86rg)zX>IuF|SKrLR9rVqcE<8;? zxap>4&xi<0xdG#;*l%UqMw9v3bgL(z#!c_GQb3c9J^jrH^pyDp^{*|m}C z2Hf}}&12V%bkTrY*Gkwn()9x_Y^A4~Z1nhm6{Be2kUM&g0Fcj+#L98fEiEa!WqOug zIhBT4BAY0IPQ74Hcz(r_RllD6+!TkyG4)3UgRi65R$>ziJTnWZqct1*=+Rp)*&xM8 z4oTOxMcNuPHu6KKW6fK`n%5a_-m+t_d=rxoIp*_w8-$1A)b`!iZ0_)un9oH!QZ9#D z9J2rIw>T15Klb^z7)*h2g1t-knm-t|`6xT!aUCAHL_$hlfj@vNlQju=j|AeLvgG;& z$te{}o)$j&gv-1y5_n&zVXQAC6MKi8F7574mI|a=wJ-LuzQC@1wdt&P;wQ&N2i#_M^o7)jx`5AR@#Rj?5mo=nAI$VG_K+A8s zbXBZ1=O_~m=%Q6$i%OXRvv8NP+JJ7XRsP5+sC>X_1C2dvQ$!(**7^I(~2~OHHF=`Q%cx}E5TW$ zKXNYXJkk{Y+E>@!zL4yW9sFNrI{oDZn{Rmy86T%9%B45Z=4-1XF$PWYomfkb>ciH$ z4P;YzEaX11mAsU%InbDCHs9IfWMQ>-~fh9$MUsVL0K(IhplIajE=y@s99>>;N=EG!8x)c10kkZ03ELIr*Dv|!HF zBsB|e6AI!rMLF@lVDpu~B|H`W8_UO}qVa%sgaqnsiDE-e=K4fE%viO_y!i6|FO&!fO0HBlACvk&gMlCC{Pwg z6BmuF_F)7KS5CMo2Hs7gyD2^;Jxj?ySvR~D`&03QW Tb0bS^=9<4<5=G$NjsxrfK=ng^ delta 215 zcmbQ&$ULu+d4e>%iIJg&rK#!Ue=K4fE%viO`No_7vCI{KaX^xrcZkmBMG+`a7Dg3V zU|`AvRbc|w^2vr#1W7=AvtXc}Fp_}S=9rXZQ51nYl@G;{1tu3L7ftr7y0=+t@?mad UiOpQ|w@X3=z^>nXZ^r?409v0z$^ZZW diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M3/TOOLCHAIN_IAR/libcordio_hci.a index 58106f595ea096b40fd65991a33074d1ecd5a298..764388437cc60050ed6b151618bf52df425cf876 100644 GIT binary patch delta 142 zcmdn;n03oz)(O(=rbcGQriLbyAFLDGXyM5Xe|ae_3vsgaqnsiEm)J4UgI7XP7Klg)OFX9Zv!klbbsq4j()fz9_6%terN Lif=YHWfcSf#s(FX delta 83 zcmdnd!?>e|ae_3viIJg&rK#m)J4UgI7XP7Ki_Lb7X9bYuHfsp2=Yt7szNcU=0^TLY5A65)5P`A%F{s7(fvS?zoVY3eiFgXdy*Lf7mp* z%p}$5n{jZ-3?o!jDkLyJxDeu4GnOKDWD%Egq{b73 z-+lMq|KEML|L=XzrF{NuN@KECTv$?6TqFy2DxS@yE19kU>$I@{Jz(bm9Hzo)Lq8Ma z^I)r=cBbbcIL6jb|5lxs1oSi5t8L##Z|!126J11p8@nA88^%Ve!6H$ z1^(-R`~T}4oY8v0YM?)KOW}5cAoy1G$AnT412OYf5QJO4I6M627>Ee;$l!E&-7XO4 z5W4AX=TQ(pg#+;*ehDWggE#{y!{3Af&<83`$(K9^N(3{HgAzg28=(9Y7QY3`8ACst zMNw#6S_O{uorkx~hKA2P%FfZ+{Nd zbAc~+foee;_B>e7K`Z#?{9s-UX#W>@{(sTPkI50%=bsyV&?K(IlB0PCmNors6{sxD&T!xrPYM*#`hdWxabtr3$D4H@n#^2p+Tt>v8Yl83? z!%ErxIsG)7s@YA$!(j^Z4ZF_9`@-{uvNBcih?3&5lFbr1d|P6B&0#N-&sFopk=Fx2 zD}qA|tU#tuDT09pk0Zx0fS~;9c~-|YCKqgAsqC11bOTFc3GxM^Ve)MvpK)XZyPsX< zz%|o3{(-LhG*8w^hi3o#?`Sztw7r8a4AhCa7PX^cC<9L=Ew zF|-D9Qaiiq8b{`o7Y5d7Z12!zi`whgIAYR{H-yBV<>eyq+M%x>ZYa;(9Urnmz3EYf zl)!?jyybuCiLaksk*;UotI4c(HfVg@5wP1!m!s313N;WH$_Gk-97K5e(##wP)J_R* zeYlk^?VGNciP+`+?aa72Y|bDi5L>61u4q|IYw$Hl-&jT5Hx)A2ZDqIhP3@cZW>w#` zzNxXd*G}oXQlRyuo`m6iF-li(Q?jSvcpAg;tR8!UT>hZulIb(pAlb2nx#HAp4(6Y% ze3xa(-Yx8FJ(IR(5Womx6(E;b1IQ!B$wK0h0L8?5TrLc9FMnT?)fcEf-jyI76S+^_ho`92U%e+&qtSFOn{F0f?zQ==Px!dc zCYvwf#Qx1;anYYOx7-opcJ%?=s`>s!yIr#CD7W*^Y_i}c^!E*_gZ}2dnd)bDfZ3-E zN*w;?AAD*B?&x)=wCf!H&<{TTqC+mn)%=jdU)Jm6J(f7u>2E@DvNJqe@AMx)vC$HD zI{gKGKK`*&HqGTeZ4}l<5_|F;;Z@5Mv69RntxVX}N)&5kQzMpgK_^T6$u`CcjNf&# z*O`6|-tq891BrthqU2XmZitfKuq=rL*kLzvW7Pad{pOwUCzNT&!k@5zdzAcd055bz zDUL>Lkp(0IL+9J&(JnT3_!=t?r?ZBiZPqf9XZ!DZDUaPJwuqiJ3~E;bW_8QXovdX3*zS&y(>Ad? zE!^d6clUPGsP#LIIqxvWMNGbs)$g+RbUf5p{{T5= zF9V1Rf1kh@{N5maDgYicv&-S}GaFhOF&<(sF|NaN3^2;>2dukVvPBFTn9LB zwnp?r^+@_X$n&t%eS)l$V~*7opAkMt9DAylWW0?FiP7N_V!Vs>#F)T(OTUE}6EP1c zI^0DvUi2Qz?sIGY1TiL%f_IMQM-Y4QD@Q;w#G^35nwUhKj_r&%TRyXgZHNovViX}& zmW>d}noR+?*y_B~HM#j)#mC1d$VKCXPn&`DcC&bLhT`QdHra(LzR4yld(Z^gQ7U}u zCTym)W*-ZTQtdp|E*97YccxerNl%)q9=lb1nQA>B7aR2t zi0-tAgpcfQW8u@-T%t4{!~c#r9*KjG{T`#`fEaH50$OM)K06`iN3O_J)TAmKtT%dd^t6B1y-L>&*4212 zOMDwhGMbMob57nh^Zg*nrd}OMgls%UL!Nr?$xRO1%u%Q0hBGP3r`Hzafrr$2)_Y4) zzWM57u%}h8H_FIuOzKn}dEs=5%vTFz;eXUua{Fm2lC=U)Kh4@g?fS8n#w?)N`Px0B fqZMn{YH8L+hksu-0_(NQiX&dk^2q;C^OgJ$cCsa+ delta 5979 zcmcIo3vg6L7QNl?6B6^8Pne04&rAYCz(77i5`t3sSP5Yf1O5;Z5|wP!C_!A8BBd_@ zi-pp4lNz<53N`Tu#Fc^sec_`Jm$KXibt0byUEQS0RWRr>E=mkY_TD#dU^2QcAWY@d z>2v$u+x@!VyZv6icp>p%OJdUqbwW;d{-nHT7;|pUU(U1~U^`75E(Uf9z@Zb)8`_09 zUj|?8yk~kD2FJ0r^IxjVG6C%Z_UckjAhQ8DK?^p*`8pr)i$SFe_ys`wiSx=`z|R+L zPXYgR!2SPq2`(sJVuxTTG}GW%1`@$@VkipMgA|S%KLCj^Z|=q6(Q1%_(1MNg<>#h= zbP1su$=<&Uq@P3YQjmTLr?-G~0g#jPAq-l$;hdgw8ss1Y74V(BiG@a&#=a>He%hMD8Km)r9ZBXaC+ZfBP4WblsCb1X@JZRiHBU{PtYayRi`R&3Vh>TO-nWkZo{4oWN__cTj#1{% zhI}{bG=v4)HXP^?Y)c_}8Mf^q`WbA0%>W#tRbsRCh&JYDqHqO^(@(y}HmF*EiKA35 zT~%7Qbn{Z^W25ga?Q9=Bd1g?74gR=clYM>lE^S-8#Z9)B?d$7{)a(NrRzXC{z{=y& z{*}d&@2w;L<&DLjeUbh+XfR__e6^LCjj!}aHB2jYY3Ykq|1hTbV}P=_w83f6SIBr@ zBSh!tH`c(IF{O%+`$rnxl#bktv`f;)fUmCX_#1!N#Fh+BXMIIn?pwxM{n27U2h;Bh zgfNKo4XekT)QLGMJYv)Fx4^Z&l6Y_`xQp&;ylZgkVEKEMgXM!$huu?GX3Rq3eaoS+ ze^}yB9ZkBNGBV6q(H|WxtdFU7;hMo>#Of`~&QxK2K^`t%e3m7NPqwiCXrpM8aJxOk zF#w~96@W})6(EN=4PYWMI_DFk^JL<5fGNaR0~8UD2Ph_v11KTJ;Hkt`fO6t2fEmPg zfE$UkAr@|?#&CdJh(-4vHB$`Usz$Tty~oS16o;&GUW_p}>c(Hc@W098BNy50i|h}V z*z1KQgI((_ERPmVo8(9_UuPxWto}&R@QIRVm z(v+KJfR{wWNhyt=RE0lE@$lYg(OSSg%J7k9iqa|ElLaS-*3H(_Swa8lsv*By5^v((;|9=10s0XfI!ZAN*YDPOgDdr`h=%5QDn z>_HFbcHy3nS5kp@j7zk6b2@BUgDlxKn{&Aipa_ ze+7^V?}Zq?4f-NW5DyHKe;{^uvH98>a~w{OApZVphLN6ib`DfZ0jk1uZJ1sXrk985 z<}m#n1M%WJEJ^DO>)0Klai?KVh^C4BGfaOKrcZ_GE6%QkQ6Y@_{~_AwFtXv>4Wy%J z#UOgn&;Zw=UW1*$L~D^eLmZb_q~7uu##rq250or?@WGoF+&z84BMWNvmfdV)#K?KR zQ+N!to5z3zv%5R%K~)Z5DaTSfY-?QF%pOs>m*pp$*gcxGblO%+KWvNx&r;&TZw)~LJyk%09Oe^`4R#K{2o z^aG^ejYW+9*fh#-D)AV@WW-~+G0HHSj3k)S$b+ejLl-NrQJ#(RjY+6{Yv3~LH)bm$ z2P}fu6XQT-#8|YZ5o6XHh%svgF&4X-#Q5yZBE}*}ZxJ->*~H@j?j)7~Dv5ExyNTTZ z)x=ml?*+ihhXd4-0jIx^7zcWYc&vBPqVeMXjdC;xrn|b?cTB^h1<2L7lvD;Nu8!=KhZx6Rjd8Tpdr4!y9@G9g zvQ~{1`5Q9e0928qaMkE}=NWj=k#+$*MvMtp5aVh#5#t25nD*VoI1!_cV7|{tJ?)1(nfij1{C za6sIzilURUhtG}{EKl;N58&-rD~YBXF*pwsNdu z;T0Cq`jYB+_G)amSVUvL>`^vZ@Mss7AMgn3v7YPBvWez=%vfj>*#}h*|C3GhqE=qO zVlhi(k3x4pc1=PTW*1fa&}Eig^bRnGXxOe;(bl>jZGX0l>{Doadxm7;JM3c74>)8L z-g@bx=aiJD6VV6_yna`J}5A|tW$u|XG%IP1X`iwR{?lvD{YmmVS75M! zVaF7Cruq32FpRB`UpKERU^r1J9}RjK-!uBaLvq(_GYNgr9NHsqP7Kkn9+4k77r~?i zJ$pc&W3F8uMXZliZVFCA7@s@|naW~wuk!+y^|vc!8D>_pBT9uzo?j0YybcN diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_core.ar index a3d9f8cba6cb0d4e3a2187fbfb452e35b169ceba..89f559614f5456380ec36302d40413e08cc29434 100644 GIT binary patch delta 184 zcmdn+jA;W93A3`B8krfJ8W>LA=Pkb3khM+#NkDA#8Bt>%6ag8f%Umb|Ji2HCf6R9a z!&GeE=lxU=#sS-KF!qrURKN%*Ah!8HfxIY+z@OIL+%SR7`zA_C!#VfX1hD}CtVKE| delta 184 zcmdn+jA;W93A3`B7#Ug`7@AMs=Pkb3khM+#NkDA#8Bt>%6ag8f%UnM()L4;~a| h!8jnf#-n^N&SX1A@y&_?w|I~Q#5POFvI`&yh;O#l&E^LH DwgwT- diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_ARM_STD/libcordio_stack.ar index a5d88a86b169041d3bdba34a9c5689c2a8a24ad0..b1db9dd65a662ec7c8c5fe5b64bd3651f0c6521b 100644 GIT binary patch delta 5621 zcmcIm4Nz3q6+ZXA`=0zPu(Kh1jn?aPHJg~q=*?G zSpS=Lz;)*8m{yE9!qid{qA!h5B-74VI=iayX?GE?FAMA^7KSR_iAguO(xMC)fZ@dINN*<|Noo?*;lOSPnoR0_sbd^zooRuE4|9-%SP@ z0M$!K5jmhEz7r&WWVt{JM!_FJ5-9!f(XbiUGNGE2vD$_Nke(n^U96`XqzB=03rPPD zUoem!0?g`yAgIB_sP8HPW@3IjFcal_fISG$o&)yKP#>kpuSTl^_P=oHGBAPbm4Ud8 zn=zr9lLuHi)(MY=c?}?&*mw|Rfx5Z?sKLZn{8v%rN#HMMK{oO410Z{$f@05nI#|j; z`C6!7lT=#`iol+RCxf$-LGeeSzw>DGj_1P;rz^8(x@XOH@sul)vt!Dvp$UG3qa&yM zQf2@#d29TX0Ag*^&&LN4OgkK75@b1Zc67Z{Xf=uGO|r9N;)nAb0mPPnZHhIC##q^L zI+UcQ_z`hh;WTp5*Q!X-T&u{e1iu`IR`(-v$G^(K+^&4Lr?M%X^zxoYVxL2okegtw z7`9rfiUB{;G70^HVM_uGvrI2Xmr|XxCU||h1X9TQ1?#zUKS@)I_Y}!R6}64EJKEtU zNlqH68)+Gg0MYOe|=>DBA??ZZA_x7!}fr2R3-gRSOcZNErT)9c?tHeSXaos&z zqX!y{SoA=0l+tS-W*A}J-hA6YNL1b4tls*?I}8T8LvWS4*PTM1ftmRI%I4varsm*m^!6l2WD z0rIUB@7j<~yW1-j(Lp`g%8HD1dBw0r`{4m{OXjQFsfA_|{=0k{>t1ZHUKM7qDGV>w z#}a)k*2g9KxKSLuo7Taq)N7v@^Uwn^7Od$Y8_SzlFPI(vGE$yMdBn$1;v?|PA zTNwTWeJr-ude&V^;77Kwsl5FoX(m@|nTxB3$yDC-inK@!%rp5JyIM}Ydln;u!TZbn zd;kI^=v#a#1Onq!k6V3l8Wfj;>ZPDKQ}u-LJ^>b#AnWl=+_Co~2gMaVzSnP1ZMbcNWu*z2lz1*!UG5i?h(GmEhVa#e4;`~fkl2k;7R2hzF3IhLP>scf@dZN z_z`f^*n%(wBH?0y9|dm)_+cs>2_VAZ1_}yIaT*k4xMKKX_Y@m+;YLJUJT4n0Fv;-6 zDwp+j@JCxD1WzEiIiVJ%Ou@LyXAkwfkA%qPi3yXz$ z!s0?D!eU;zVfC}bh1Q}^rvp@KWldxY(cU{sMkudrq%pj&nOMmpp0ZAM@MMPb)x0O2 zIe5--oNwSq=i+=V&ONSv#s^*|lX*okW#l1hL8o!*D-5;{-`12YJ~Ej5hHXglXZw5~iL1 z35|R;0$?>C#I#TsZl(&0tUS7$C1Lv97Lpd)j;wfER?o%3B;NT?DTE(rA<3b=K0akA ziCg-S??XOfz~r$e%2Qt!Pk?8&;!2-J0UYzJcqf(awDIyr63-8{l1TF>OZ*Z_uH2d8 z_laJ$YD2B$J!;G8y}mVFEiAI8h!?U1nHTxMNm4)(dG>FK>e=`4ZLPVD{D#pH;43?00s5KoW`|_Lp|Z! zybaL__~sFLxXvPB6TP}>SS-NHg0KTzFoZrA7KLlr$0O!55%~{BJOx7`B$PL1N=c-dmv!N#cms2e@a$HSDzCzeGgrSK4OUNo zSseds7xDd3#Q%74TI3(dN7Kf6|DewHB$hk0(9cL>uE}UKl4-2P^mt+ob!h7{sV&u{ z^peKqbXU5`XqdD&#pkshqJMkV^gR8i9olPm>215oXl)TveWdB}{vOGpl_f~ui4LTC zvZNPBYvwJGqDPzB_J!osHkV2H=Av$`ZL@UE=kaYz6{ptLAmwKpqHYb>$ujlap2%4a zE&qx%Z-Ot5no~vv^lkT8*+`O^!0}uh+WRiHG%AoWv_f{y2)sf_vA*0 s>FG;%*_F5429u}Zfp2vAy#87x);y9tJv(Ku@}l__%hP^+R{0?NzZ^Ut%>V!Z delta 5684 zcmcIm4Nz3q6+Y+v3An(*g1fp1OF&%>C<~^>)Z#+SDk!L0hgIuC(ei&tUA?}Na7o#R5YezYio(6ZES5uqfSj}%%WCNJEiBoeQ*D?4gS5E z?|t`t=iGD8y}S3m`;!aKfeX%#gQ&Iw?l#bM2Jm6v(kFmJg*w#0M--j&W;pxzO@Mgn1|*wPBZgF$`J1ozheW<3Zo zP(y;4+zL9fvOtVRVKa#FD9ZuExe27r>WJh{Iyc_3Z0ktznfti?5!iBy|e2?xizf({I=}q%s%rCyQ%0IYOgNK zGzFIZrRdOvM9j@Kr9gJIT`QY_r;PH7J%N;x5n9m#EXgurJgj;Jb^GzF_%E{?53-A% zlH!2B&5hUCkruSg5G$b13)oi=^9C%Il{0}Jv65>7Y2JZ^tUEP}p~Qf#6DVW-zSvxg{p|w@&A#t8xK-B=%6-H7 z6Hw|;1|H;AX(pI63;G&xd%s1VKOkk*yqoLGFXG-%DIMkJ@I8NDvV^T@#ivGvJWuLH zyYzQR0bu?Bj>uRz7yHU^SSYJPS?4r%u*Lvx#6p(VieDd-uMZDy;c$mv;WKW)wURHY z6P1#neXkX-$pLGlW%eipD7V$F8@66)l;4z^#0|n*_>67!+$39V`S1$;{fz#e8Ku0W zx1ZME{*c#J%gVm3Ji$iSqb1uEsqMWmBtAu4qwz~4+OPKR*T*m%( zO37zkr<57|mCdHtN)y=D6KGZGkMJFV{~bb)1pR|AMA-lc&yj641IUi`3vqrS&M(IK z#TY-0FX;gz!UIS#0RXb@=SvrQuyIYb2Taw>utw;e35a&-yoE9;=s7!sP+aaT{yefzz-c&{APzpYZ0Uz`2S%d1NAu#LB!%ejqJ4 z4nNZ0iOe$x$6*yGI}834t#WG;EeVr%Vji}$@jJ=8hs`GnG+&X}>pQ8CLu@dIoWc5e;CpQ3E}~ zPR-81{1bV??sQh&g3ip>zQ1(U;)$93P)oE z0rth%BIHHc{5(mFviW%uG;wc;&~T73BKKr88$CEU9bu8o+0om(*+TZ zGkH+VVe{U{i)t1C{ktJ48{jFt<*~EnmfZrO4^gT(5^u!K;e{-D@PBaFXW+a|P zEV$w(K#BDUqyro^^67^N<-2U;(F>)*Xg%nA;M68+xCH|Rea~su1Gp90&pyD#n8DHx z((X9J&dn6;Y|cTn3TMT@k4}%3r_*L!rEkklYAx4WIkfSXP|L>tNs)3BnJ$KhXm5Mz z=EB^EFkf&av+6@QR$fVa&&&3fN_nhpCpp{5nb=Jt-&eG$3&b4kVP71gZF-i}ZK3_8 z(xEd)-(M%Jfy-4Rnc9WsmD8hN9`|?Y zo@YvW7tdUwF?<8nC}@Lu)hyPkw+I(sHlmC9M%L!v6t3G$MXOF08&XV5zZYv?IK^kv zVx^iwado86r(QA5EUGwkEl#Ntr$!CBLOd6?Sazl2(5joosU9<_M)&VRn-V%+0?8!~ z?R2kLI?8aDXmryaWA-lz&AP@a-O4co7%hukt1Xf$Q)8ub)1?p0*_4E4bD&y!%$!XL zqvfz`H(!=Eek(G%U2D^%ndXJPM7#V4X?-LwmFmzopO-x0dTXxQwX@fy+1X|aF3if5 zUl<=PbeGC~6C#2``}I=!HzOi~UF)cqujWPz-S5b@!e}A*ds%xtA~>{yB zg#L3fU%BAQ&&h~yeyDzo117L}ok1ffi~}@XY_pG5Fb|Rd&^k9YHY5SDO}@>1$o$O< Hq7|3{V%sgaqnse#c(rFd>A+i+y(A~` delta 135 zcmccB!+fiUd4e>%iIJg&rHRQ#rFd>A+jz3TKC#X7xbKUj2+UGec0duhl{{SpMWC-@ hy%|)%1Zal%=IHfZTu1_9o0)d8v%my43+(ga007R7C^i59 diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_sec.a index 57500f02bf72612637c4a53edbb8b57325cd0bbb..7572fa316ab134119f153bdcfa6ded2e665b4408 100644 GIT binary patch delta 70 ycmX@(e8zc#G`p#hnX##X(MBavMi_gu9pg@RIOiY7Nj5m=9REp9IA@-u9tQxcRTC8e delta 70 ycmX@(e8zc#G`oqBp@pT1$wnnnMi_gu9pg@RIOiY7Nj5m=9REp9IA@-u9tQxh@e@J- diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_GCC_ARM/libcordio_stack.a index 80fa72e5c66ff4abcd5c1ac424a2666db463e9f6..a115a3aa9181bf777c1bdb3930fa7cb86ad4b077 100644 GIT binary patch delta 4784 zcmcIo4Nz3q6+Y*_{dpiiyZpF|u(B*BprWpTmWFBq>ceR5_|u|?=L~$;?HgX>;|<{xM%|uxKiC6|2_-Y6Sofm3bgTsOr@di|5a4&AM0l5!IC_@NYB_Iimz10nBPvJZE)Kwro2t2aAe3BUOu~Dr;)=}Uqq+&*1BI<4TYAKIkdFu z+^yYWq|MQ`9V~E!;$m_fTKmaaMoBsJZmm;Wd0|n=onHTs6TMU|9*i|~ zWb+dBW)WTa%axWU>CuDxtxA>RRd9EW^6l-r-$G{o>B@?qTJjq5)qztm-`pg{7ni=Q zy;~92ToXI&^d<{7Bv(w%p#HZ|{J6l}p$$;!b zI=2ew8Be})yvQBgmBfxB6Gh9B1E}sH(9I=F_V5ZKcn7L<*tZGJ5+S}>YS=` z0TUzzV>bt4yvf$Wqvry$cTUv+U&GZ=<9C%bh88FmYMu<90dtGzn&^ZZ8CeqFoPrYa z!r~%0DrU)Kp*#_=rEn!=PYu|j78hyFvoet$yE!qsPRxJ>9^t%$&Yn1wK5C5tr@t2jTAyun++FIS6c>d=n$Ua!cw}ZEyKK-XUYp^s%x{ctuA!Z zvwZMZ7iOWG+S}933oX2UYA;U5RrJ~RA)y03yxfV|!Q*;>`r8MpHKrzM(E5El_WP7* z#jTikJA$2MQ6TfF)9+Pm4y1rbv89QgJbrk8g;phviQ{MUPy1c|y@f9SMys`@pOoBS z-tv#q59*N$fATuK2I-TOH04l{Q#;%e7wh#)ibr`;ITUb$$duW*xA4-LXm|6~8JjF} zLjrH{5%nG=B29#gCQnj^D2q#lt5%V0#Rjd^ci$s88Q_3m9`=P` zo-T@)B<7uhd750#gtu>$nCCU{CkOpS2aEa9f>Qw|365u{_~Sg>Em(~k;Bz7KbQY10 z>mn_202}#Z96_&dilWDwOuAyhIK<1;z9!wA$xl@ttF&S|+qVQwY{yY4fgQ1;4NKTb zD`uFd^2SYJ{tqyoMaf(~#9T6F@HXFg-oc&`%9pHQs+3`IoA{;^w)zTs%wFEhUo)JG z>1L-4@CHpA8_(Kg?7D>b-KYADf`);jb>bMd0x za1s}+K7Se3_V1<)u0~5jr;^)|Xv%i1&9!v=5kVJ~IrZoUTo7US==}CwW(}XVe~v@s zaAD?kd_Uyhk#kG{SDTF#tn55->L0gblFbNfuXXD781j-)Zmzy9m25Ho4$0NW<`a8_ z;T)ag)EA8>YhnyRL`TmcwV`NsDob+er{3gxMDy`sNeFVeAGgxQg_l*-=Wi_~8_Pg-I- zgV?lX=+s|pA|EG)r>RCMe`uHB)URYo%j3d@^2enG_HIdVn$+LX<>JtDOQn8UU4m18 t_Ejl6zDscEbvvc!lfwn?ds4=LaAD~uQa?+$u=O+P!_;u0Mly|0`7b@uq+$R7 delta 4965 zcmcIo3s6+o8UD|?`(j<#g8O&ZcMZo6Cz^0 z>mxCYPKzG(Mr#uvok@&!MqKM^(aJP+>NwLG)?#aY6`Q7*Ftuz#DhinX=fYiBViSnE zGauhQ-~YJ(fA0P7UDkif(ss(yn5-|z&+|?%nAYUkL8O-e`UgM^eQ;lpIv>brA&u7Y z0r^RzuJpkaAdP;j9!LSw7_Qa*EZ~_&ARLlA0o&(0s_b5v!fu56h5~uYX#wcz^4I0 z#nv1U1|Wg(_NoVi_W*=1h4dv(S4u$Oc>jg_0*z1!Q79fMjD5YO&=&9;H)QDszShX3 zggOEfru-vL6|TKS?17BpLPwOas-n}X3VYg!Bk=0dy~ZfviMl!CQ~`510teSWtycvl z#J#CD;-Lt?k&B0fd05BzeQP6UQR+BybfR6&ft5M~cmDK)NTp#WI0AK-mqtPshNxYb zQjpK2ifoqGwM@D>i>-WWrM6R;aPY8RY!I_VvcFOM?B<=%G$Ldbw7ysGm9j;Pn=8KN zef1T(?DPA>W}UUmU_N?yUxPaoD0YWp!e;Ov9*AmfDy`J65!Vz-!tyzyA#5PAx!mHF zjB{qCnq1H;xZL78-`pk|&X9ncNPD38$~ocC$?IL~`1)1{;Ahf@U8U<*q)&YP(Dy>R z71O^}7a&m%p?-I{Q0j4`Yy2G5fv1FByvZ;t6S3KezEx&#gF zB%Z&m_(h$ugmwy5oeOprr~H}ZfAn4LepiFUljz0WO>65Dx~N$bwg|3P?T%27squIi z%t@{823I|m30u?v?3`zoc&5~)>`vlrrEt;YiV2LXCxzHm8CMLvi49wH#`ESm=Xz}Z zW0*zL>cK2A?v~Q_j;e+gKBtnQxjtE6JmFNcuc{%*-_`-Wx~KM6{$1%jgSU?#?OgCw zRPC%{Wglndm^`!>a*HZ!O5qeYn$n54d={DOEJJ13+EHFp8t8g9i)?8&u(nTT#_mER z1szO4euKHYr^Eu`ia}Aj*~0EmNDe#Mn8{XsT0;)X3%i6gcA?55_bnzC_RZCn_=^~c zA&`Se03&qB1!U69K9@XAann*vFfEjny3DjB&g`p0693$M+0!ALmJs z297}?Wk66)K+OPrr|H9i#XWIU`vxY;WqY<-S>tUR*~Qi@wz6ZlE!s1vds!Iuc3kD~ zF6Cv%sg)UeEn3_~C}Tz2tSq~8Et4I#S6+PXr5{fI$-^#}EANr~!ABX6zeDg& z&u9LMEYi(R_NPjIO{b8t;n1&e`r|~GsNKI=xjVHu{ng6!dj_Y!ta;n5xLlZMy!3AU zfd=8R1my`}Yz-6}&&9fu+r7#xLDqjlW|s{Ix;wO49}^xYIL;5vQ$nj(B8+Z>?T}t9 zx^bGGhrqFLf;lH7h#s*>^ls!sG@+djkc|(JGKM%nVvO4>ohj|;aEke&&&RzE-~f^H z2YjhGWC`YRp%@oe1u?hD>Y*=A-$*7P&sg~P1jc9K+Tln|A{*`Q;$1VlY;v?Ur#c$yU|iEFXWa+v=E=XM^7@fJt$Yo zOn*ak zKvnqg1&_Cp#WAX)_!M0w&qmIr_?-NJWE)f;RGdNG4RSg<>cg94wN~{}Dtxt{Bw3=A zld<%*_`x4%rn0yxiNVS=x=#JMW-42{)E*>-^tNG`k3Hxtp=;w*MUHzMoB!=Rx@RcS zoxS#8T{TTgh&W9?i=7>=rLp?ql0A6kr*y9_TKeUBT06okZxekjSM>`1?gV`Bu{d%Oh~j3Mob$>a_z^0F-Mh@Br#isd}~CBE4Bw0ye<4l-Q;PED_4Fm id@V`!8A#;5A{f=JK_|R6v)>o~nx;A_$_znMlJY--C;@r^ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_core.a index 66636579d88e49919a670c17476efda996880a48..56b4f40a1c5e9396b0c0cf49fd91e1d1ed08ec99 100644 GIT binary patch delta 215 zcmbQ&$ULu+d4e>%sgaqnsiDE-e=K4fE%viO_y!i6|FO&!fO0HBlACvk&gMlCC{Pwg z6BmuF_F)7KSC<1pXABsZ+Aa0smpj%iIJg&rK!o}e=K4fE%viO`No_7vCI{KaX^xrcZkmBMG+`a7Dg3V zU|`CFqT-VcqX?3K_-4UCJz=N-*v8EJF->{oSfv)1Ip+{hA} Px#n+|L=m{R;{ZDVSnfl{ diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_hci.a index 1798b322929b29c17c81496360f3fadbcda927e5..6aed31880d14c99d5b4d5ab61c09e0d77b38d949 100644 GIT binary patch delta 142 zcmdn;n03oz)(O(=rbcGQriR9oAFLDGXyM5X;T)j{Zbs`BOw5s%rNf& delta 142 zcmdn;n03oz)(O(=CPs!9mZlbyAFLDGXyM5X<(q=|o9A&)SBDCifdzt$+pA#$n;)#R oSAlZO!Ll}&Q}dt#VDq-`b7Z_Kh$6Bfn2{A`2Sm-KIL1dp0JXX?O8@`> diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_sec.a index e9a236a209cd61142b1431215fcdebf469141e07..50087f708d7b5e4aa11135851881545a2d291694 100644 GIT binary patch delta 83 zcmdnd!?>e|ae_3vsgaqnsiDbaJ4UgI7XM+~&324u1z;SI+-41-^?Wda&G!_{MPMAD LtoUYQQ&vF$#kduc delta 83 zcmdnd!?>e|ae_3viIJg&rK#m)J4UgI7XP7Ki_Lb7X9Zv!klbbsq4j()#hdRbn2W$T MKw0t4#-^--0M2+7%m4rY diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a b/features/FEATURE_BLE/targets/TARGET_CORDIO/stack/lib/TARGET_M4/TOOLCHAIN_IAR/libcordio_stack.a index 9dcb05103f1abcc12b33308b04173dbd027a283c..403021767e33c951c9a4038ea58f8130d6d233f0 100644 GIT binary patch delta 5820 zcmcIo4Nz5O8h*d;{2+vIxtH!mK)8TjLD35rVbRKf6tpzaEX_<|G_}Spf7)`S_JEn< z+P1pa=G$$om8P;qbNJB?nuWN{>`#`LMAK>K{74(K?Dx4!gB6v3U#^`Av^~K~BAQ5IqULBrvf)s)lYFsXFIt$V@ zgl0H<&koX$;lxmo{vR&R1L+DN4?GEdp!HQ;lE)kYIfT+;kV7c9f&61w<^=hQpRQSU$xG^^0J?HviqFTuSSD1_DNpb$1~>jkZ^;s^5EUxIQi za5f$k6KecdU_t}cS8#nWe+Q^P3+-nHZN%gVFF$c@aP$*UtthezSJ!S_6p@l1dan_s zuP~Q?t8Z3Nk)12*oXpiYIH$m^8m~Ut&$aTn#;5LjDC?5!YK&N=d#v)Y+I3D--jL#I zT;0-oqeXo5!@tH@#L=f(oMyOue6Mot9KhE1D0GZJDaF$5)Z_En;~A!A6upS)+soN~ z1A`uYVo8$h(mfhWGcyWm{CN`Jz*um2Qpbo(y3|1o3m5*Sc z!tas87(l!D&#SD0t4u7~!jjl|v2F`XW|3kmQM`DU$fKX$!X9UnV$fzH#~<^uBj1Jc z5JV)l?HFf1w)-QZOnE7`6D<8tWBXf->l8H-o1wdESqIbOwz1b#t-Zuqys}O%{$26n z74<9NG#m0@aZ^M0w_V+kUfU7f@3z3oiYaQrp%iUSr@TJ=G>fU}h?E8_gp8!-mWuU* zGm3nHwJJL_V8xQg%C#|J$rq|Sq_(OeDe%_Guh&!;r5%juh=xkTqXLP6MP=TqS2`mq zrxv@l^ku3T(#ZOc3O@}tTYeQf%_vp^;T>5(36O&jS1nJ=fWYFC_ML0$*z)d)vXO{Q zJl@FkS;659!UFv&WWyDih1Ipc1@70%h`Yx_3Y%Lvw|ji|gnyKEPv{=sZ{FgP?mHwL zUCm~MT$U_>=sQsm_r;Mr`W`d1I#VDcCfFtG+L1U0E37X zfJ|Z)z)OssKH|Xuxx}8}CV+H+n@Ao8Fot+Iz^%m500qR^0ON>p)r*PI*&W0V+yul~ z08@x>#7I-AAx_Lty<*rZHImhdWWk(Lk>fFuk}KUTB6Jq%Y{xO<92KjSr{&es8vZOR zbUey`Ei!esNt9LaaIt1Nzs( zF=D)v^Ta~{x`^@4V{wb!fa5&K5jX>R#CV7Eh|$mU)E^J9hh(&WpBQK8Ffq>1XT<2| zJTm(6K^HX=&^zv5GL(rEah8b(;{GSbfbk}K#MWIblVyq{yV$>Ro!;Kf($ujsfS-#w zK9n$+J}BBI z%T5s(AlsBDalID!mmGA6#qqL@e;O^a??Zp*P~GmYIh3Y+Y6F;hX+U0#zvg?7QjE)b z&n4}q7=Oq29=1(XWvi~Br;{=M!Y&W%w5Uef{TsSGe5_qmVGLer_n$yHoM_za3senN}`%1^wGB@)rQ9 z&}3136&i~yK`bzI{`@VrB`5<((J)nE0Jb;a@N|S7!;e7u&)C;4 z0xv0(MZ3hp^<#fyjERq)W>NaZci3OT?Dqt|t8i-#4Ym|2SrU}Cist<+Z^6jcrVe}b zO|9YXpgu3)aK|lWsVVDZL(}#7uC=ud8;TBp&_B(6yi$!iq>c}C#_rwI0nz;eZtafZ zhKBHz<0VHvhi1$HUT;{waA@&_V)E8h0bvIYH7!&s_v!>|hCClD-Z5m29CO@V5h=lg#Id%fl8n>%FflrOj2LIJk{Aoe~}myNW__={z1g4_yCe10U}TsZFUq8yRohjr;8Wc*p~2iG)57U zL~DkUphn98w*)J&G7-<|8GlS$8XpxYT02>icyR^mr`(C#ZkA}>rKIs%D!)#VHCVFo z?a}@zBb_3ug7vg3QLk*rLc3Tj*{!50Nw}v?xeAp(kVkM9ATU4css$tmsDxOrc z_k4`7J;6L&wTtrmITmsXaJOC5Utk#FM)djsp7^OjSGrxW?@&J*_5AO4(J?z@5$6z7 zsAoI%q&q}?kFTW;QA0gl)U(nd7}<;|#nKzVs_YhpUd*vQR+Kq0$N%Dv%@_5<6^AH1 z%3{rTP5&b;E`8}ycJC02V&_S|b%aIM>%2TC%2YhZnCp!(JSWv6>!oGSw-;`+{TQOQqk0@(XIV&6dt2S*%?88&67aCY#}Njd$*6U%)zK(YW-+_oNFw zu_ohVN`Lo+l$a2@u~zQVwl6=tovhd-Tg-c(4t31X0I0z~}E0tdl-IFn* zu3SD9V+PLGadJMK5t59=Htv_}6GNKdyv#i%FX}NdChyDzd1h$xMj78Y`UBC*RJUmt z{H$p6D$9oU(#)Hwlw?{oF8!aYmHFnUP7Zx~#Oae>P*Tn1H8d{$nPw%%8@y{%v-_;_ zW@azV9~0DUm#Hzf)p4IXeWaRnDL`}y4mNG>9 z60j+VwPaSf*eNujC=%2OiSPnq36|+#4P~QH|B8hf9EBid6*Yrsdd}OoVY6!GcPHO` z_ndR@Ip^MY-?{ImttoM1bK>d*H7_@(@TLOqqkEm(3YRl27uX&X?-v8R3gFNI7Y*%F zI$wjn+C^u24T58A?c$f}nk1lI!n3-X31rm)CuqS&IN#y}emSUg0lx%j-|M`h6ZplV z_4izr1-CjK?B_ks6 zSyLd&pJz_**4&wa@0_v1)1Wxp({J>+0zLAxy)}Cs?aS_XBsKi#On!# zY;k74?9^YWVl#%D!}D~j#%^+((pZ{NJijSN6jewW{FB)B`6p7D$gbkC*WUvG8xR~K zU>P#~Mj;re@O$Jh5xwHSFR)sE7DV-Cmc&kpRhwBd<6f#CMC9P zCdX0c&xSk)9rSYJ!;P3Eh`}+ z`P_;#(xDZ_lJE6T{mbi%-S0&CEl_8UP4-n+X4OC6JE(3_sY}aPr1~S7;vWL!#ijL4 zf}SGAd+H&&u&{nUWM-BsKJHI9%;b)`8E%)PWrD9}!kO*AYh_FNCbJ$7mwT46W`DGp z+s^cd149@@`66r4CmGQv4UcF&^E$X*tR(K62q~V~^|SjX_Lc3g>?`Y=82LcW1S1QH z_bi8^-pIs(ax}?h&Ys{pygX#iu1v2!6Yb{`>N3olQuT_o{vvgMC&F+m7T^}k1qUmEECmuR0nXQrzwochcr-~h5ji(= zV(+$q=zo$sMCCBqsx;xFd(gY!9sAnrWGj!bioN$?Pp5V5I?1v28P&=yF<#3H4#PS# z#@qa@TdBsUdw2hkH)6d0Z{6%|5tE}jjc!A2Ue9-Ko@5g-Gtk$4Hg6+}51Zl(Ht#VM zcbMYmHg8U!n{&HJnT7Kx$DQI5O@C!+N=+>8D+(hzhhw4|iu1+Pv)EJG!(v0Lom0xs z36wjwNUz$%-eB4TxUPYp3IZGRL*(5kuM3g)nLUXlEL-m&H-*?g9ALM>MwAorIR$>ba{GVdqUN%d6&Wyw9)x+PL<}i|{_2)o^6rd_ht`3uz zgvrapIKZrUyb!<4N z3~V>!7dz6Isy(1u5ln7vWCU7V3vl-~3=#+XQQD3R)%$#WOat=60Nu~#C}D}3Kz zv2Qbry#&*{J8D5y4r9T_f*QHgk~a0IsO)0-b8qbK@Y^iox}#iVkzlOP?uuW?Qd3sR zhUU9ZcCKt`Yb^fP+e6ZlkJhO}4l5IVy|JCU{a}gkxwM~`wzWm29G&pqCzRaFZA<2l zEG;V~Ul=jMcerD|Qg=ZAwu|A(xRGk>@Pljz)mD7_07e>>6(9;=D9Kn`9mGih_>Kc4 z;|3ze{@66iYbtT3p)$r}Q8CIasthOS((r?>jH4ARt5JT9@{CTXJZs=G>oa=uPzNk^ zKO@FK6Ns@iO(I6Gw-ck+a$+oLQ;G2%n?{VKj=mKr>*>U!0q!T304j+w;2h!~%Pfmb!~%^mo+MA4k^aVck7V z3JgGXcMz@`z1Msc9%LlD0DeP^4jYJZHCGd304Gh`B*YQ;uStFs<1(VSSvrd67-{XVQs+ z&iEf}!gG!}#D-Y({AVm&(*myiHql7>)2QdnF6t|SBc|EKF|ynmhnCrP;kiF(dC4wv zzCp_~WZ7*OjcD;6>9i_?aHnR7?lG8RZk#w1hbfN7Z;C?U8Likw_j?x(2>N{2`TOkN z5$5N!U`eub`x3r&OsGOH%HlT;4bjBwjkoaJ)DVqRKRSyqH*XI41p>d(oqGKW-kM?_ zMg<~!ksPm=x9|z~nB&$k7O!t-($ldQ6i&UuA>CySRruVJuwPKb>%Sc*MfTqx7{+Ot zBK@jAJ-ValH&;lXC7EN4TZ>-$g!EeS08P?*DWd=0f}`T~k^|B?Gg5(=f;RNdGNCJ?TG?m+tDa`|O*S^-5-m3+dy z^%UglxH#`lHv`cf$f2iq$=ecxnt;Br}(kB$y%{I}w6Sn#Zx6kHVgC%XR9CbeX&*~L&q Jf1tYa{|Cc+X0iYP From ba0f18c9ab683d39f55e6f05500f44a0326f43fd Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Wed, 2 May 2018 17:38:59 +0100 Subject: [PATCH 150/274] Fix casing in MemorySecurityDb.h --- .../ble/pal/{MemorySecurityDB.h => MemorySecurityDb.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/ble/pal/{MemorySecurityDB.h => MemorySecurityDb.h} (100%) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h similarity index 100% rename from features/FEATURE_BLE/ble/pal/MemorySecurityDB.h rename to features/FEATURE_BLE/ble/pal/MemorySecurityDb.h From 4e5639f5ca42adf0da5ce9f07525213f3ef83500 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 2 May 2018 17:51:48 +0100 Subject: [PATCH 151/274] BLE: Support encryption with secure connection key. --- features/FEATURE_BLE/ble/SecurityManager.h | 35 ++++++++++++++----- .../source/generic/GenericSecurityManager.cpp | 28 +++++++++++++-- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 11294a7461..dd6c4b3865 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -967,15 +967,31 @@ public: */ ble_error_t getLinkSecurity(ble::connection_handle_t connectionHandle, LinkSecurityStatus_t *securityStatus) { ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); - ble_error_t status = getLinkEncryption(connectionHandle, &encryption); - /* legacy support limits the return values */ - if (encryption.value() == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { - *securityStatus = ENCRYPTED; - } else { - *securityStatus = (LinkSecurityStatus_t)encryption.value(); + ble_error_t err = getLinkEncryption(connectionHandle, &encryption); + if (err) { + return err; } - return status; + switch (encryption.value()) { + case ble::link_encryption_t::NOT_ENCRYPTED: + *securityStatus = NOT_ENCRYPTED; + break; + case ble::link_encryption_t::ENCRYPTION_IN_PROGRESS: + *securityStatus = ENCRYPTION_IN_PROGRESS; + break; + case ble::link_encryption_t::ENCRYPTED: + case ble::link_encryption_t::ENCRYPTED_WITH_MITM: + case ble::link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM: + *securityStatus = ENCRYPTED; + break; + default: + // should never happen + MBED_ASSERT(false); + *securityStatus = NOT_ENCRYPTED; + break; + } + + return BLE_ERROR_NONE; } /** @@ -1079,7 +1095,10 @@ private: SecurityManager::SecurityMode_t securityMode; if (result == ble::link_encryption_t::ENCRYPTED) { securityMode = SECURITY_MODE_ENCRYPTION_NO_MITM; - } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { + } else if ( + result == ble::link_encryption_t::ENCRYPTED_WITH_MITM || + result == ble::link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { securityMode = SECURITY_MODE_ENCRYPTION_WITH_MITM; } else { securityMode = SECURITY_MODE_ENCRYPTION_OPEN_LINK; diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 857377776d..d4c0529e55 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -369,7 +369,11 @@ ble_error_t GenericSecurityManager::getLinkEncryption( if (cb->encrypted) { if (cb->ltk_mitm_protected || cb->mitm_performed) { - *encryption = link_encryption_t::ENCRYPTED_WITH_MITM; + if (cb->secure_connections_paired) { + *encryption = link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM; + } else { + *encryption = link_encryption_t::ENCRYPTED_WITH_MITM; + } } else { *encryption = link_encryption_t::ENCRYPTED; } @@ -408,7 +412,9 @@ ble_error_t GenericSecurityManager::setLinkEncryption( } else if (encryption == link_encryption_t::ENCRYPTED) { /* only change if we're not already encrypted with mitm */ - if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM) { + if (current_encryption != link_encryption_t::ENCRYPTED_WITH_MITM || + current_encryption != link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { cb->encryption_requested = true; return enable_encryption(connection); } @@ -423,6 +429,19 @@ ble_error_t GenericSecurityManager::setLinkEncryption( return requestAuthentication(connection); } + } else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { + + if (cb->ltk_mitm_protected && + cb->secure_connections_paired && ! + cb->encrypted + ) { + cb->encryption_requested = true; + return enable_encryption(connection); + } else { + cb->encryption_requested = true; + return requestAuthentication(connection); + } + } else { return BLE_ERROR_INVALID_PARAM; } @@ -1059,7 +1078,10 @@ void GenericSecurityManager::on_link_encryption_result( cb->encryption_failed = false; cb->encrypted = true; - } else if (result == link_encryption_t::ENCRYPTED_WITH_MITM) { + } else if ( + result == link_encryption_t::ENCRYPTED_WITH_MITM || + result == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM + ) { cb->encryption_requested = false; cb->encryption_failed = false; From 7e043ead968f185d0b6bd6f6927eef667a86e03c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 2 May 2018 17:52:39 +0100 Subject: [PATCH 152/274] Nordic BLE: Add stub implementation of remove_peer_csrk in security manager. --- .../TARGET_NRF5/source/nRF5xPalSecurityManager.cpp | 5 +++++ .../TARGET_NRF5/source/nRF5xPalSecurityManager.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index dfad1a671d..42fb338e22 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -527,6 +527,11 @@ ble_error_t nRF5xSecurityManager::set_peer_csrk( return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t nRF5xSecurityManager::remove_peer_csrk(connection_handle_t connection) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 35de6ba86b..0afb6c4deb 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -249,6 +249,11 @@ public: sign_count_t sign_counter ); + /** + * @see ::ble::pal::SecurityManager::remove_peer_csrk + */ + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); + //////////////////////////////////////////////////////////////////////////// // Authentication From 4f1e574eff8624d31ed51822145367b65ebc7805 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 2 May 2018 18:14:54 +0100 Subject: [PATCH 153/274] Cordio GattServer: Fix uses of designated initializer. These are not legal in C++ code. --- .../TARGET_NRF5/source/nRF5xGattServer.cpp | 128 +++++++++--------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 8bcdd7d07a..67d8a7a960 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -29,38 +29,38 @@ namespace { static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID_OFFSET } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 0 + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 0 } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID } } }; @@ -260,9 +260,9 @@ ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { - .len = *lengthP, - .offset = 0, - .p_value = buffer, + /* .len = */ *lengthP, + /* .offset = */ 0, + /* .p_value = */ buffer, }; ASSERT_TRUE( ERROR_NONE == @@ -302,9 +302,9 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute ble_error_t returnValue = BLE_ERROR_NONE; ble_gatts_value_t value = { - .len = len, - .offset = 0, - .p_value = const_cast(buffer), + /* .len = */ len, + /* .offset = */ 0, + /* .p_value = */ const_cast(buffer), }; if (localOnly) { @@ -611,14 +611,14 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) // success, signal it to the softdevice ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 1, - .offset = input_req.offset, - .len = input_req.len, - .p_data = input_req.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 1, + /* .offset = */ input_req.offset, + /* .len = */ input_req.len, + /* .p_data = */ input_req.data } } }; @@ -639,12 +639,12 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .offset = req->offset, - .len = req->length, - .data = req->data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; @@ -661,9 +661,9 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) // FIXME can't use ::write here, this function doesn't take the offset into account ... ble_gatts_value_t value = { - .len = req->length, - .offset = req->offset, - .p_value = req->data + /* .len = */ req->length, + /* .offset = */ req->offset, + /* .p_value = */ req->data }; uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value); if (update_err) { @@ -688,25 +688,25 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), - .update = 1, - .offset = cbParams.offset, - .len = cbParams.len, - .p_data = cbParams.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), + /* .update = */ 1, + /* .offset = */ cbParams.offset, + /* .len = */ cbParams.len, + /* .p_data = */ cbParams.data } } }; @@ -740,21 +740,21 @@ void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) } case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { GattReadAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.read.offset, - .len = 0, - .data = NULL, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.read.offset, + /* .len = */ 0, + /* .data = */ NULL, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_READ, - .params = { - .read = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_READ, + /* .params = */ { + /* .read = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeRead(&cbParams) } } }; From 0a59e00b230456da4cbc41986f3f089f8ab48f45 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 2 May 2018 19:15:24 +0100 Subject: [PATCH 154/274] Nordic BLE: Update GATT server security management This patch refines permission applied to characteristic and descriptors; instead of a single level of permission , each characteristic receives a permission for the read operation, one for the write operation and another one for the update operation. As a consequence, updates are not sent if the link does not cover the update permission requirement. Descriptors also benefits individually from read and write permission. --- .../source/btle/custom/custom_helper.cpp | 89 +++++++++---------- .../source/btle/custom/custom_helper.h | 8 +- .../TARGET_NRF5/source/nRF5xGattServer.cpp | 50 +++++++---- 3 files changed, 79 insertions(+), 68 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.cpp index bc46d3d58d..6a85387330 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.cpp @@ -30,6 +30,34 @@ typedef struct { static unsigned uuidTableEntries = 0; /* current usage of the table */ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES]; +namespace { + +static void set_perm(ble_gap_conn_sec_mode_t& dest, GattAttribute::Security_t src) { + switch (src.value()) { + case GattAttribute::Security_t::NONE: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dest); + break; + + case GattAttribute::Security_t::UNAUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dest); + break; + + case GattAttribute::Security_t::AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&dest); + break; + + case GattAttribute::Security_t::SC_AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dest); + break; + + default: + break; + } +} + +} + + void custom_reset_128bits_uuid_table() { uuidTableEntries = 0; } @@ -203,7 +231,9 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -226,8 +256,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Notification requires cccd */ memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); cccd_md.vloc = BLE_GATTS_VLOC_STACK; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + set_perm(cccd_md.read_perm, GattAttribute::Security_t::NONE); + set_perm(cccd_md.write_perm, update_security); } ble_gatts_char_md_t char_md = {0}; @@ -256,49 +286,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Always set variable size */ attr_md.vlen = has_variable_len; - if (char_props.read || char_props.notify || char_props.indicate) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm); - break; - default: - break; - }; - } - - if (char_props.write || char_props.write_wo_resp) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm); - break; - default: - break; - }; - } + set_perm(attr_md.read_perm, read_security); + set_perm(attr_md.write_perm, write_security); ble_gatts_attr_t attr_char_value = {0}; @@ -342,7 +331,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle) + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security) { /* Descriptor metadata */ ble_gatts_attr_md_t desc_md = {0}; @@ -352,8 +343,8 @@ error_t custom_add_in_descriptor(uint16_t char_handle, desc_md.vlen = has_variable_len; /* Make it readable and writable */ - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); + set_perm(desc_md.read_perm, read_security); + set_perm(desc_md.write_perm, write_security); ble_gatts_attr_t attr_desc = {0}; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.h index 93480b873b..88b8db48ce 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/custom/custom_helper.h @@ -45,7 +45,9 @@ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid); error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -64,7 +66,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle); + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security); #ifdef __cplusplus } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 67d8a7a960..05ca55a57b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -25,6 +25,7 @@ #include "btle/custom/custom_helper.h" #include "nRF5xn.h" +#include "nrf_ble_gap.h" namespace { @@ -164,21 +165,25 @@ ble_error_t nRF5xGattServer::addService(GattService &service) } ASSERT_TRUE ( ERROR_NONE == - custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, - &nordicUUID, - p_char->getProperties(), - p_char->getRequiredSecurity(), - p_char->getValueAttribute().getValuePtr(), - p_char->getValueAttribute().getLength(), - p_char->getValueAttribute().getMaxLength(), - p_char->getValueAttribute().hasVariableLength(), - userDescriptionDescriptorValuePtr, - userDescriptionDescriptorValueLen, - presentationFormatDescriptorValuePtr, - presentationFormatDescriptorValueLen, - p_char->isReadAuthorizationEnabled(), - p_char->isWriteAuthorizationEnabled(), - &nrfCharacteristicHandles[characteristicCount]), + custom_add_in_characteristic( + BLE_GATT_HANDLE_INVALID, + &nordicUUID, + p_char->getProperties(), + p_char->getReadSecurityRequirement(), + p_char->getWriteSecurityRequirement(), + p_char->getUpdateSecurityRequirement(), + p_char->getValueAttribute().getValuePtr(), + p_char->getValueAttribute().getLength(), + p_char->getValueAttribute().getMaxLength(), + p_char->getValueAttribute().hasVariableLength(), + userDescriptionDescriptorValuePtr, + userDescriptionDescriptorValueLen, + presentationFormatDescriptorValuePtr, + presentationFormatDescriptorValueLen, + p_char->isReadAuthorizationEnabled(), + p_char->isWriteAuthorizationEnabled(), + &nrfCharacteristicHandles[characteristicCount] + ), BLE_ERROR_PARAM_OUT_OF_RANGE ); /* Update the characteristic handle */ @@ -218,7 +223,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service) p_desc->getLength(), p_desc->getMaxLength(), p_desc->hasVariableLength(), - &nrfDescriptorHandles[descriptorCount]), + &nrfDescriptorHandles[descriptorCount], + p_desc->getReadSecurityRequirement(), + p_desc->getWriteSecurityRequirement()), BLE_ERROR_PARAM_OUT_OF_RANGE); p_descriptors[descriptorCount] = p_desc; @@ -345,7 +352,16 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute } } - if (updatesEnabled) { + bool updates_permitted = false; + ble_gap_conn_sec_t connection_security; + uint32_t err = sd_ble_gap_conn_sec_get(connectionHandle, &connection_security); + if (!err && + (connection_security.sec_mode.sm == 1) && + (connection_security.sec_mode.lv >= p_characteristics[characteristicIndex]->getUpdateSecurityRequirement().value())) { + updates_permitted = true; + } + + if (updatesEnabled && updates_permitted) { error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); if (error != ERROR_NONE) { switch (error) { From 1a35f3e2174f8fd1ea3c266e2ccfda945f16f8a2 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 8 May 2018 17:49:22 +0100 Subject: [PATCH 155/274] fixed case in name --- .../ble/pal/{MemorySecurityDB.h => MemorySecurityDb.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/ble/pal/{MemorySecurityDB.h => MemorySecurityDb.h} (100%) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDB.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h similarity index 100% rename from features/FEATURE_BLE/ble/pal/MemorySecurityDB.h rename to features/FEATURE_BLE/ble/pal/MemorySecurityDb.h From 214656a9eee59d46afd6f4133392b956a8a4cfe5 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 8 May 2018 17:56:38 +0100 Subject: [PATCH 156/274] fix case in #include --- features/FEATURE_BLE/ble/pal/MemorySecurityDb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h b/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h index 24783f42c9..81ef33fd6e 100644 --- a/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h +++ b/features/FEATURE_BLE/ble/pal/MemorySecurityDb.h @@ -18,7 +18,7 @@ #define PAL_MEMORY_SECURITY_DB_H_ #include "ble/Gap.h" -#include "SecurityDB.h" +#include "SecurityDb.h" namespace ble { namespace pal { From b8fe37a00e70daae8484ed53e4c7d8a3068ac3eb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 11:01:10 +0100 Subject: [PATCH 157/274] disable ECDH if the platform doesn't support it otherwise you get linker errors --- .../TARGET_NRF5/source/nRF5xPalSecurityManager.cpp | 14 ++++++++++++-- .../TARGET_NRF5/source/nRF5xPalSecurityManager.h | 4 ++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp index fec4ff6885..6766597db7 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.cpp @@ -106,6 +106,7 @@ nRF5xSecurityManager::~nRF5xSecurityManager() ble_error_t nRF5xSecurityManager::initialize() { +#if defined(MBEDTLS_ECDH_C) if (_crypto.generate_keys( make_ArrayView(X), make_ArrayView(Y), @@ -115,6 +116,8 @@ ble_error_t nRF5xSecurityManager::initialize() } return BLE_ERROR_INTERNAL_STACK_FAILURE; +#endif + return BLE_ERROR_NONE; } ble_error_t nRF5xSecurityManager::terminate() @@ -210,6 +213,7 @@ nRF5xSecurityManager::get_resolving_list() { const nRF5xSecurityManager::resolving_list_entry_t* nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { +#if defined(MBEDTLS_ECDH_C) typedef byte_array_t hash_t; for (size_t i = 0; i < resolving_list_entry_count; ++i) { @@ -233,6 +237,7 @@ nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { return &entry; } } +#endif return NULL; } @@ -715,6 +720,7 @@ ble_error_t nRF5xSecurityManager::send_keypress_notification( ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() { +#if defined(MBEDTLS_ECDH_C) ble_gap_lesc_p256_pk_t own_secret; ble_gap_lesc_oob_data_t oob_data; @@ -734,6 +740,8 @@ ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() } return convert_sd_error(err); +#endif + return BLE_ERROR_NOT_IMPLEMENTED; } nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() @@ -877,6 +885,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) } case BLE_GAP_EVT_LESC_DHKEY_REQUEST: { +#if defined(MBEDTLS_ECDH_C) const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = gap_evt.params.lesc_dhkey_request; @@ -895,7 +904,7 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) if (dhkey_request.oobd_req) { handler->on_secure_connections_oob_request(connection); } - +#endif return true; } @@ -1138,9 +1147,10 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( } // copy public keys used +#if defined(MBEDTLS_ECDH_C) memcpy(pairing_cb.own_pk.pk, X.data(), X.size()); memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size()); - +#endif return keyset; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index bd9206b790..8d75a686b0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -20,7 +20,9 @@ #include "ble/BLETypes.h" #include "ble/pal/PalSecurityManager.h" #include "nrf_ble.h" +#if defined(MBEDTLS_ECDH_C) #include "nRF5xCrypto.h" +#endif namespace ble { namespace pal { @@ -381,10 +383,12 @@ private: void release_all_pairing_cb(); pairing_control_block_t* _control_blocks; +#if defined(MBEDTLS_ECDH_C) CryptoToolbox _crypto; ble::public_key_coord_t X; ble::public_key_coord_t Y; ble::public_key_coord_t secret; +#endif static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_WHITELIST_IRK_MAX_COUNT; From c02b318436fa9ede110e48621c43e2b880fd218b Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 11:37:33 +0100 Subject: [PATCH 158/274] fixed case in filename --- features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h | 2 +- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h index b5c7bb9ca5..2d56c98f3e 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioBLE.h @@ -30,7 +30,7 @@ #include "CordioPalGenericAccessService.h" #include "ble/generic/GenericGap.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/MemorySecurityDB.h" +#include "ble/pal/MemorySecurityDb.h" #include "ble/pal/SimpleEventQueue.h" namespace ble { 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 99954738cb..dfaf59cc26 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,7 @@ #include "ble/BLEInstanceBase.h" #include "ble/generic/GenericGattClient.h" #include "ble/generic/GenericSecurityManager.h" -#include "ble/pal/MemorySecurityDB.h" +#include "ble/pal/MemorySecurityDb.h" #include "ble/pal/SimpleEventQueue.h" #include "nRF5xPalSecurityManager.h" From b98ffa48dad54f7dfb8be36f3c0d3d9d2324ea0b Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:16:26 +0100 Subject: [PATCH 159/274] fix uppercase X in nrf5x --- .../TARGET_NRF5/source/btle/btle.cpp | 10 +- .../TARGET_NRF5/source/nRF5XPalGattClient.cpp | 98 +++++++++---------- .../TARGET_NRF5/source/nRF5XPalGattClient.h | 8 +- .../TARGET_NRF5/source/nRF5xGap.cpp | 4 +- .../TARGET_NRF5/source/nRF5xn.cpp | 4 +- .../TARGET_NRF5x/source/btle/btle.cpp | 8 +- .../source/nRF5XPalGattClient.cpp | 98 +++++++++---------- .../TARGET_NRF5x/source/nRF5XPalGattClient.h | 8 +- .../TARGET_NRF5x/source/nRF5xn.cpp | 4 +- 9 files changed, 121 insertions(+), 121 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp index 8839fd19db..ee361f3011 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/btle/btle.cpp @@ -50,8 +50,8 @@ extern "C" { #include "nrf_ble_hci.h" -#include "nRF5XPalGattClient.h" -#include "nRF5XPalSecurityManager.h" +#include "nRF5xPalGattClient.h" +#include "nRF5xPalSecurityManager.h" bool isEventsSignaled = false; @@ -163,7 +163,7 @@ error_t btle_init(void) void btle_handler(ble_evt_t *p_ble_evt) { - using ble::pal::vendor::nordic::nRF5XGattClient; + using ble::pal::vendor::nordic::nRF5xGattClient; using ble::pal::vendor::nordic::nRF5xSecurityManager; /* Library service handlers */ @@ -179,7 +179,7 @@ void btle_handler(ble_evt_t *p_ble_evt) #endif #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) - nRF5XGattClient::handle_events(p_ble_evt); + nRF5xGattClient::handle_events(p_ble_evt); #endif nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); @@ -222,7 +222,7 @@ void btle_handler(ble_evt_t *p_ble_evt) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) // Close all pending discoveries for this connection - nRF5XGattClient::handle_connection_termination(handle); + nRF5xGattClient::handle_connection_termination(handle); #endif gap.processDisconnectionEvent(handle, reason); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp index cba1ea60d4..404b3bdc96 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp @@ -16,7 +16,7 @@ #include -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" #include "ble/pal/PalGattClient.h" #include "ble/pal/SimpleAttServerMessage.h" @@ -159,30 +159,30 @@ static const size_t characteristic_declaration_length = 1 + 2 + 16; } // end of anonymous namespace -nRF5XGattClient::nRF5XGattClient() : +nRF5xGattClient::nRF5xGattClient() : ble::pal::GattClient(), _procedures() { } -nRF5XGattClient::~nRF5XGattClient() +nRF5xGattClient::~nRF5xGattClient() { terminate(); } -ble_error_t nRF5XGattClient::initialize() +ble_error_t nRF5xGattClient::initialize() { return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::exchange_mtu(connection_handle_t connection) +ble_error_t nRF5xGattClient::exchange_mtu(connection_handle_t connection) { // FIXME: implement when SD 140 5.x.x is present // (see sd_ble_gatts_exchange_mtu_reply) return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5XGattClient::get_mtu_size( +ble_error_t nRF5xGattClient::get_mtu_size( connection_handle_t connection_handle, uint16_t& mtu_size ) { #if (NRF_SD_BLE_API_VERSION >= 3) @@ -195,7 +195,7 @@ ble_error_t nRF5XGattClient::get_mtu_size( return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::discover_primary_service( +ble_error_t nRF5xGattClient::discover_primary_service( connection_handle_t connection, attribute_handle_t discovery_range_begining ) { @@ -204,7 +204,7 @@ ble_error_t nRF5XGattClient::discover_primary_service( ); } -ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( +ble_error_t nRF5xGattClient::discover_primary_service_by_service_uuid( connection_handle_t connection_handle, attribute_handle_t discovery_range_beginning, const UUID& uuid @@ -214,7 +214,7 @@ ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( ); } -ble_error_t nRF5XGattClient::find_included_service( +ble_error_t nRF5xGattClient::find_included_service( connection_handle_t connection_handle, attribute_handle_range_t service_range ) { @@ -223,7 +223,7 @@ ble_error_t nRF5XGattClient::find_included_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( +ble_error_t nRF5xGattClient::discover_characteristics_of_a_service( connection_handle_t connection_handle, attribute_handle_range_t discovery_range ) { @@ -232,7 +232,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_descriptors( +ble_error_t nRF5xGattClient::discover_characteristics_descriptors( connection_handle_t connection_handle, attribute_handle_range_t descriptors_discovery_range ) { @@ -241,7 +241,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_descriptors( ); } -ble_error_t nRF5XGattClient::read_attribute_value( +ble_error_t nRF5xGattClient::read_attribute_value( connection_handle_t connection_handle, attribute_handle_t attribute_handle ) { @@ -250,7 +250,7 @@ ble_error_t nRF5XGattClient::read_attribute_value( ); } -ble_error_t nRF5XGattClient::read_using_characteristic_uuid( +ble_error_t nRF5xGattClient::read_using_characteristic_uuid( connection_handle_t connection_handle, attribute_handle_range_t read_range, const UUID& uuid @@ -260,7 +260,7 @@ ble_error_t nRF5XGattClient::read_using_characteristic_uuid( ); } -ble_error_t nRF5XGattClient::read_attribute_blob( +ble_error_t nRF5xGattClient::read_attribute_blob( connection_handle_t connection, attribute_handle_t attribute_handle, uint16_t offset @@ -270,7 +270,7 @@ ble_error_t nRF5XGattClient::read_attribute_blob( ); } -ble_error_t nRF5XGattClient::read_multiple_characteristic_values( +ble_error_t nRF5xGattClient::read_multiple_characteristic_values( connection_handle_t connection, const ArrayView& characteristic_handles ) { @@ -279,7 +279,7 @@ ble_error_t nRF5XGattClient::read_multiple_characteristic_values( ); } -ble_error_t nRF5XGattClient::write_without_response( +ble_error_t nRF5xGattClient::write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -297,7 +297,7 @@ ble_error_t nRF5XGattClient::write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::signed_write_without_response( +ble_error_t nRF5xGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -315,7 +315,7 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::write_attribute( +ble_error_t nRF5xGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, const ArrayView& value @@ -325,7 +325,7 @@ ble_error_t nRF5XGattClient::write_attribute( ); } -ble_error_t nRF5XGattClient::queue_prepare_write( +ble_error_t nRF5xGattClient::queue_prepare_write( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value, @@ -336,7 +336,7 @@ ble_error_t nRF5XGattClient::queue_prepare_write( ); } -ble_error_t nRF5XGattClient::execute_write_queue( +ble_error_t nRF5xGattClient::execute_write_queue( connection_handle_t connection_handle, bool execute ) { @@ -367,7 +367,7 @@ ble_error_t nRF5XGattClient::execute_write_queue( * @note Commands such as write without response or signed write without response * are not procedures. */ -struct nRF5XGattClient::GattProcedure { +struct nRF5xGattClient::GattProcedure { /** * Initialize the procedure. * @@ -424,7 +424,7 @@ struct nRF5XGattClient::GattProcedure { * Given that such procedure expects a single event type from the soft device, * error handling can be generalized. */ -struct nRF5XGattClient::RegularGattProcedure : GattProcedure { +struct nRF5xGattClient::RegularGattProcedure : GattProcedure { /** * Construct a RegularGattProcedure. @@ -483,7 +483,7 @@ protected: * In such case a read request is issued for each service attribute handle * to extract that information. */ -struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { typedef ArrayView services_array_t; @@ -692,7 +692,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { * response it is possible to reconstruct it by keeping a copy of the UUID to * find. */ -struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -766,7 +766,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProce /** * Procedure that manage Find Included Services transactions. */ -struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { +struct nRF5xGattClient::FindIncludedServicesProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -841,7 +841,7 @@ struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { * In such case a read request is issued for each attribute handle of * characteristics that exposes a long UUID. */ -struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Data structure returned by the function flatten_response. */ @@ -1060,7 +1060,7 @@ struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Procedure that handle discovery of characteristic descriptors. */ -struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { DiscoverDescriptorsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1151,7 +1151,7 @@ struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { /** * Procedure that handle read of attribute handles. */ -struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeProcedure : RegularGattProcedure { ReadAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1178,7 +1178,7 @@ struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { /** * Procedure that handle read of characteristic using characteristic UUID. */ -struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { ReadUsingCharacteristicUUIDProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1265,7 +1265,7 @@ struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProced /** * Procedure that handles read blob transactions. */ -struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { ReadAttributeBlobProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_BLOB_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1291,7 +1291,7 @@ struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { /** * Procedure that handles Read Multiple Characteristic Values transactions. */ -struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { ReadMultipleCharacteristicsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1321,7 +1321,7 @@ struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProced /** * Procedure that handles Write transactions. */ -struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::WriteAttributeProcedure : RegularGattProcedure { WriteAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::WRITE_REQUEST, BLE_GATTC_EVT_WRITE_RSP @@ -1352,7 +1352,7 @@ struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { /** * Procedure that handles Prepare Write transactions. */ -struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { +struct nRF5xGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { QueuePrepareWriteProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1398,7 +1398,7 @@ struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { /** * Procedure that handles Execute Write transactions. */ -struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { +struct nRF5xGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { ExecuteWriteQueueProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1437,7 +1437,7 @@ struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { }; // NOTE: position after declaration of GattProcedure on purpose. -ble_error_t nRF5XGattClient::terminate() +ble_error_t nRF5xGattClient::terminate() { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i]) { @@ -1450,7 +1450,7 @@ ble_error_t nRF5XGattClient::terminate() } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1473,7 +1473,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1496,7 +1496,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2 ) { @@ -1520,7 +1520,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2, const A3& a3 ) { @@ -1543,7 +1543,7 @@ ble_error_t nRF5XGattClient::launch_procedure( return err; } -nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( +nRF5xGattClient::GattProcedure* nRF5xGattClient::get_procedure( connection_handle_t connection ) const { for (size_t i = 0; i < max_procedures_count; ++i) { @@ -1554,7 +1554,7 @@ nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( return NULL; } -bool nRF5XGattClient::register_procedure(GattProcedure *p) +bool nRF5xGattClient::register_procedure(GattProcedure *p) { if (get_procedure(p->connection_handle)) { return false; @@ -1570,7 +1570,7 @@ bool nRF5XGattClient::register_procedure(GattProcedure *p) return false; } -bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) +bool nRF5xGattClient::remove_procedure(nRF5xGattClient::GattProcedure* p) { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i] == p) { @@ -1583,13 +1583,13 @@ bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) } // singleton of the ARM Cordio client -nRF5XGattClient& nRF5XGattClient::get_client() +nRF5xGattClient& nRF5xGattClient::get_client() { - static nRF5XGattClient _client; + static nRF5xGattClient _client; return _client; } -void nRF5XGattClient::handle_events(const ble_evt_t *evt) { +void nRF5xGattClient::handle_events(const ble_evt_t *evt) { switch (evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: case BLE_GATTC_EVT_REL_DISC_RSP: @@ -1611,7 +1611,7 @@ void nRF5XGattClient::handle_events(const ble_evt_t *evt) { } } -void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_procedure_event(const ble_evt_t &evt) { GattProcedure* p = get_procedure(evt.evt.gattc_evt.conn_handle); if (p) { @@ -1619,7 +1619,7 @@ void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_hvx_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; const ble_gattc_evt_hvx_t &hvx_evt = evt.evt.gattc_evt.params.hvx; @@ -1650,7 +1650,7 @@ void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_timeout_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; GattProcedure* p = get_procedure(connection); @@ -1661,7 +1661,7 @@ void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) on_transaction_timeout(connection); } -void nRF5XGattClient::handle_connection_termination(connection_handle_t connection) +void nRF5xGattClient::handle_connection_termination(connection_handle_t connection) { GattProcedure* p = get_client().get_procedure(connection); if (p) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h index ede03ce3f4..986fe1b48f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h @@ -34,12 +34,12 @@ namespace nordic { /** * Implementation of pal::GattClient for the Nordic stack. */ -class nRF5XGattClient : public ble::pal::GattClient { +class nRF5xGattClient : public ble::pal::GattClient { public: - nRF5XGattClient(); + nRF5xGattClient(); - virtual ~nRF5XGattClient(); + virtual ~nRF5xGattClient(); /** * see pal::GattClient::initialize . @@ -184,7 +184,7 @@ public: ); // singleton of the ARM Cordio client - static nRF5XGattClient& get_client(); + static nRF5xGattClient& get_client(); /** * Function call from btle.cpp diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp index 3d3c085adc..9c3566625a 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGap.cpp @@ -26,7 +26,7 @@ #include "ble_advdata.h" #include "headers/nrf_ble_hci.h" #include "ble/pal/ConnectionEventMonitor.h" -#include "nRF5XPalSecurityManager.h" +#include "nRF5xPalSecurityManager.h" using ble::pal::vendor::nordic::nRF5xSecurityManager; typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; @@ -490,7 +490,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { /* If a device is using Resolvable Private Addresses Section 1.3.2.2 (Core spec v4.2 volume 6 part B), - it shall also have an Identity Address that is either a Public or Random Static address type.” + it shall also have an Identity Address that is either a Public or Random Static address type. To establish a connection, a static address must be provided by the application to the SoftDevice. The SoftDevice resolves the address and connects to the right device if it is available. */ addr.addr_id_peer = 1; 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 a326fa336c..0f25e1634b 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 @@ -31,7 +31,7 @@ extern "C" { #include "softdevice_handler.h" } -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" /** * The singleton which represents the nRF51822 transport for the BLE. @@ -62,7 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())) + gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())) { } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index 5d6def57ac..e1bbfa0327 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -62,7 +62,7 @@ extern "C" { #include "headers/ble_hci.h" -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" // Make this volatile at it will be set in interrupt context @@ -271,7 +271,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) #if NRF_SDK14PLUS_EVENT_HANDLERS (void)p_context; // Keep compiler happy #endif - using ble::pal::vendor::nordic::nRF5XGattClient; + using ble::pal::vendor::nordic::nRF5xGattClient; // In SDK14+, all other modules from the SDK will be registered independently as softdevice events observers #if !NRF_SDK14PLUS_EVENT_HANDLERS @@ -293,7 +293,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) #endif #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) - nRF5XGattClient::handle_events(p_ble_evt); + nRF5xGattClient::handle_events(p_ble_evt); #endif nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); @@ -362,7 +362,7 @@ static void btle_handler(ble_evt_t *p_ble_evt) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) // Close all pending discoveries for this connection - nRF5XGattClient::handle_connection_termination(handle); + nRF5xGattClient::handle_connection_termination(handle); #endif gap.processDisconnectionEvent(handle, reason); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp index ebd194cd76..1778a102f1 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp @@ -16,7 +16,7 @@ #include -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" #include "ble/pal/PalGattClient.h" #include "ble/pal/SimpleAttServerMessage.h" @@ -161,30 +161,30 @@ static const size_t characteristic_declaration_length = 1 + 2 + 16; } // end of anonymous namespace -nRF5XGattClient::nRF5XGattClient() : +nRF5xGattClient::nRF5xGattClient() : ble::pal::GattClient(), _procedures() { } -nRF5XGattClient::~nRF5XGattClient() +nRF5xGattClient::~nRF5xGattClient() { terminate(); } -ble_error_t nRF5XGattClient::initialize() +ble_error_t nRF5xGattClient::initialize() { return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::exchange_mtu(connection_handle_t connection) +ble_error_t nRF5xGattClient::exchange_mtu(connection_handle_t connection) { // FIXME: implement when SD 140 5.x.x is present // (see sd_ble_gatts_exchange_mtu_reply) return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t nRF5XGattClient::get_mtu_size( +ble_error_t nRF5xGattClient::get_mtu_size( connection_handle_t connection_handle, uint16_t& mtu_size ) { #if (NRF_SD_BLE_API_VERSION >= 3) @@ -197,7 +197,7 @@ ble_error_t nRF5XGattClient::get_mtu_size( return BLE_ERROR_NONE; } -ble_error_t nRF5XGattClient::discover_primary_service( +ble_error_t nRF5xGattClient::discover_primary_service( connection_handle_t connection, attribute_handle_t discovery_range_begining ) { @@ -206,7 +206,7 @@ ble_error_t nRF5XGattClient::discover_primary_service( ); } -ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( +ble_error_t nRF5xGattClient::discover_primary_service_by_service_uuid( connection_handle_t connection_handle, attribute_handle_t discovery_range_beginning, const UUID& uuid @@ -216,7 +216,7 @@ ble_error_t nRF5XGattClient::discover_primary_service_by_service_uuid( ); } -ble_error_t nRF5XGattClient::find_included_service( +ble_error_t nRF5xGattClient::find_included_service( connection_handle_t connection_handle, attribute_handle_range_t service_range ) { @@ -225,7 +225,7 @@ ble_error_t nRF5XGattClient::find_included_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( +ble_error_t nRF5xGattClient::discover_characteristics_of_a_service( connection_handle_t connection_handle, attribute_handle_range_t discovery_range ) { @@ -234,7 +234,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_of_a_service( ); } -ble_error_t nRF5XGattClient::discover_characteristics_descriptors( +ble_error_t nRF5xGattClient::discover_characteristics_descriptors( connection_handle_t connection_handle, attribute_handle_range_t descriptors_discovery_range ) { @@ -243,7 +243,7 @@ ble_error_t nRF5XGattClient::discover_characteristics_descriptors( ); } -ble_error_t nRF5XGattClient::read_attribute_value( +ble_error_t nRF5xGattClient::read_attribute_value( connection_handle_t connection_handle, attribute_handle_t attribute_handle ) { @@ -252,7 +252,7 @@ ble_error_t nRF5XGattClient::read_attribute_value( ); } -ble_error_t nRF5XGattClient::read_using_characteristic_uuid( +ble_error_t nRF5xGattClient::read_using_characteristic_uuid( connection_handle_t connection_handle, attribute_handle_range_t read_range, const UUID& uuid @@ -262,7 +262,7 @@ ble_error_t nRF5XGattClient::read_using_characteristic_uuid( ); } -ble_error_t nRF5XGattClient::read_attribute_blob( +ble_error_t nRF5xGattClient::read_attribute_blob( connection_handle_t connection, attribute_handle_t attribute_handle, uint16_t offset @@ -272,7 +272,7 @@ ble_error_t nRF5XGattClient::read_attribute_blob( ); } -ble_error_t nRF5XGattClient::read_multiple_characteristic_values( +ble_error_t nRF5xGattClient::read_multiple_characteristic_values( connection_handle_t connection, const ArrayView& characteristic_handles ) { @@ -281,7 +281,7 @@ ble_error_t nRF5XGattClient::read_multiple_characteristic_values( ); } -ble_error_t nRF5XGattClient::write_without_response( +ble_error_t nRF5xGattClient::write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -299,7 +299,7 @@ ble_error_t nRF5XGattClient::write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::signed_write_without_response( +ble_error_t nRF5xGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value @@ -317,7 +317,7 @@ ble_error_t nRF5XGattClient::signed_write_without_response( return convert_sd_error(err); } -ble_error_t nRF5XGattClient::write_attribute( +ble_error_t nRF5xGattClient::write_attribute( connection_handle_t connection_handle, attribute_handle_t attribute_handle, const ArrayView& value @@ -327,7 +327,7 @@ ble_error_t nRF5XGattClient::write_attribute( ); } -ble_error_t nRF5XGattClient::queue_prepare_write( +ble_error_t nRF5xGattClient::queue_prepare_write( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, const ArrayView& value, @@ -338,7 +338,7 @@ ble_error_t nRF5XGattClient::queue_prepare_write( ); } -ble_error_t nRF5XGattClient::execute_write_queue( +ble_error_t nRF5xGattClient::execute_write_queue( connection_handle_t connection_handle, bool execute ) { @@ -369,7 +369,7 @@ ble_error_t nRF5XGattClient::execute_write_queue( * @note Commands such as write without response or signed write without response * are not procedures. */ -struct nRF5XGattClient::GattProcedure { +struct nRF5xGattClient::GattProcedure { /** * Initialize the procedure. * @@ -426,7 +426,7 @@ struct nRF5XGattClient::GattProcedure { * Given that such procedure expects a single event type from the soft device, * error handling can be generalized. */ -struct nRF5XGattClient::RegularGattProcedure : GattProcedure { +struct nRF5xGattClient::RegularGattProcedure : GattProcedure { /** * Construct a RegularGattProcedure. @@ -485,7 +485,7 @@ protected: * In such case a read request is issued for each service attribute handle * to extract that information. */ -struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { typedef ArrayView services_array_t; @@ -694,7 +694,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceProcedure : GattProcedure { * response it is possible to reconstruct it by keeping a copy of the UUID to * find. */ -struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -768,7 +768,7 @@ struct nRF5XGattClient::DiscoverPrimaryServiceByUUIDProcedure : RegularGattProce /** * Procedure that manage Find Included Services transactions. */ -struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { +struct nRF5xGattClient::FindIncludedServicesProcedure : RegularGattProcedure { typedef ArrayView services_array_t; @@ -843,7 +843,7 @@ struct nRF5XGattClient::FindIncludedServicesProcedure : RegularGattProcedure { * In such case a read request is issued for each attribute handle of * characteristics that exposes a long UUID. */ -struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { +struct nRF5xGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Data structure returned by the function flatten_response. */ @@ -1062,7 +1062,7 @@ struct nRF5XGattClient::DiscoverCharacteristicsProcedure : GattProcedure { /** * Procedure that handle discovery of characteristic descriptors. */ -struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { +struct nRF5xGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { DiscoverDescriptorsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1153,7 +1153,7 @@ struct nRF5XGattClient::DiscoverDescriptorsProcedure : RegularGattProcedure { /** * Procedure that handle read of attribute handles. */ -struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeProcedure : RegularGattProcedure { ReadAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1180,7 +1180,7 @@ struct nRF5XGattClient::ReadAttributeProcedure : RegularGattProcedure { /** * Procedure that handle read of characteristic using characteristic UUID. */ -struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProcedure { ReadUsingCharacteristicUUIDProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1267,7 +1267,7 @@ struct nRF5XGattClient::ReadUsingCharacteristicUUIDProcedure : RegularGattProced /** * Procedure that handles read blob transactions. */ -struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { ReadAttributeBlobProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::READ_BLOB_REQUEST, BLE_GATTC_EVT_READ_RSP @@ -1293,7 +1293,7 @@ struct nRF5XGattClient::ReadAttributeBlobProcedure : RegularGattProcedure { /** * Procedure that handles Read Multiple Characteristic Values transactions. */ -struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { +struct nRF5xGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProcedure { ReadMultipleCharacteristicsProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1323,7 +1323,7 @@ struct nRF5XGattClient::ReadMultipleCharacteristicsProcedure : RegularGattProced /** * Procedure that handles Write transactions. */ -struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { +struct nRF5xGattClient::WriteAttributeProcedure : RegularGattProcedure { WriteAttributeProcedure(connection_handle_t connection) : RegularGattProcedure( connection, AttributeOpcode::WRITE_REQUEST, BLE_GATTC_EVT_WRITE_RSP @@ -1354,7 +1354,7 @@ struct nRF5XGattClient::WriteAttributeProcedure : RegularGattProcedure { /** * Procedure that handles Prepare Write transactions. */ -struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { +struct nRF5xGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { QueuePrepareWriteProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1400,7 +1400,7 @@ struct nRF5XGattClient::QueuePrepareWriteProcedure : RegularGattProcedure { /** * Procedure that handles Execute Write transactions. */ -struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { +struct nRF5xGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { ExecuteWriteQueueProcedure(connection_handle_t connection) : RegularGattProcedure( connection, @@ -1439,7 +1439,7 @@ struct nRF5XGattClient::ExecuteWriteQueueProcedure : RegularGattProcedure { }; // NOTE: position after declaration of GattProcedure on purpose. -ble_error_t nRF5XGattClient::terminate() +ble_error_t nRF5xGattClient::terminate() { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i]) { @@ -1452,7 +1452,7 @@ ble_error_t nRF5XGattClient::terminate() } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1475,7 +1475,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1 ) { ProcType* p = new(std::nothrow) ProcType(connection); @@ -1498,7 +1498,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2 ) { @@ -1522,7 +1522,7 @@ ble_error_t nRF5XGattClient::launch_procedure( } template -ble_error_t nRF5XGattClient::launch_procedure( +ble_error_t nRF5xGattClient::launch_procedure( connection_handle_t connection, const A0& a0, const A1& a1, const A2& a2, const A3& a3 ) { @@ -1545,7 +1545,7 @@ ble_error_t nRF5XGattClient::launch_procedure( return err; } -nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( +nRF5xGattClient::GattProcedure* nRF5xGattClient::get_procedure( connection_handle_t connection ) const { for (size_t i = 0; i < max_procedures_count; ++i) { @@ -1556,7 +1556,7 @@ nRF5XGattClient::GattProcedure* nRF5XGattClient::get_procedure( return NULL; } -bool nRF5XGattClient::register_procedure(GattProcedure *p) +bool nRF5xGattClient::register_procedure(GattProcedure *p) { if (get_procedure(p->connection_handle)) { return false; @@ -1572,7 +1572,7 @@ bool nRF5XGattClient::register_procedure(GattProcedure *p) return false; } -bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) +bool nRF5xGattClient::remove_procedure(nRF5xGattClient::GattProcedure* p) { for (size_t i = 0; i < max_procedures_count; ++i) { if (_procedures[i] == p) { @@ -1585,13 +1585,13 @@ bool nRF5XGattClient::remove_procedure(nRF5XGattClient::GattProcedure* p) } // singleton of the ARM Cordio client -nRF5XGattClient& nRF5XGattClient::get_client() +nRF5xGattClient& nRF5xGattClient::get_client() { - static nRF5XGattClient _client; + static nRF5xGattClient _client; return _client; } -void nRF5XGattClient::handle_events(const ble_evt_t *evt) { +void nRF5xGattClient::handle_events(const ble_evt_t *evt) { switch (evt->header.evt_id) { case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: case BLE_GATTC_EVT_REL_DISC_RSP: @@ -1613,7 +1613,7 @@ void nRF5XGattClient::handle_events(const ble_evt_t *evt) { } } -void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_procedure_event(const ble_evt_t &evt) { GattProcedure* p = get_procedure(evt.evt.gattc_evt.conn_handle); if (p) { @@ -1621,7 +1621,7 @@ void nRF5XGattClient::handle_procedure_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_hvx_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; const ble_gattc_evt_hvx_t &hvx_evt = evt.evt.gattc_evt.params.hvx; @@ -1652,7 +1652,7 @@ void nRF5XGattClient::handle_hvx_event(const ble_evt_t &evt) } } -void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) +void nRF5xGattClient::handle_timeout_event(const ble_evt_t &evt) { connection_handle_t connection = evt.evt.gattc_evt.conn_handle; GattProcedure* p = get_procedure(connection); @@ -1663,7 +1663,7 @@ void nRF5XGattClient::handle_timeout_event(const ble_evt_t &evt) on_transaction_timeout(connection); } -void nRF5XGattClient::handle_connection_termination(connection_handle_t connection) +void nRF5xGattClient::handle_connection_termination(connection_handle_t connection) { GattProcedure* p = get_client().get_procedure(connection); if (p) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h index 79633d6fa3..6c298aa3e3 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h @@ -34,12 +34,12 @@ namespace nordic { /** * Implementation of pal::GattClient for the Nordic stack. */ -class nRF5XGattClient : public ble::pal::GattClient { +class nRF5xGattClient : public ble::pal::GattClient { public: - nRF5XGattClient(); + nRF5xGattClient(); - virtual ~nRF5XGattClient(); + virtual ~nRF5xGattClient(); /** * see pal::GattClient::initialize . @@ -184,7 +184,7 @@ public: ); // singleton of the ARM Cordio client - static nRF5XGattClient& get_client(); + static nRF5xGattClient& get_client(); /** * Function call from btle.cpp diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp index 7bc8b821b7..e9448d68ed 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp @@ -31,7 +31,7 @@ extern "C" { #include "nrf_sdh.h" } -#include "nRF5XPalGattClient.h" +#include "nRF5xPalGattClient.h" /** * The singleton which represents the nRF51822 transport for the BLE. @@ -62,7 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5XGattClient::get_client())), + gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())), securityManagerInstance(NULL) { } From 79b3bc4fcea68a6a0a81253ec42fdc8f460e3432 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:18:26 +0100 Subject: [PATCH 160/274] fix case --- .../source/{nRF5XPalGattClient.cpp => nRF5xPalGattClient.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/{nRF5XPalGattClient.cpp => nRF5xPalGattClient.cpp} (100%) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalGattClient.cpp similarity index 100% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalGattClient.cpp From 367fe345ba4b43287e9202f9789101d85fe08e41 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:18:42 +0100 Subject: [PATCH 161/274] fix case --- .../TARGET_NRF5/source/{nRF5XCrypto.cpp => nRF5xCrypto.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/{nRF5XCrypto.cpp => nRF5xCrypto.cpp} (100%) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp similarity index 100% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XCrypto.cpp rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp From 37b11d8ac5cdd61545ef64796c675b98eca83615 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:18:55 +0100 Subject: [PATCH 162/274] fix case --- .../source/{nRF5XPalGattClient.h => nRF5xPalGattClient.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/{nRF5XPalGattClient.h => nRF5xPalGattClient.h} (100%) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalGattClient.h similarity index 100% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalGattClient.h From b4d7bb602049677646f1692450a1676e7c79d81a Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:19:27 +0100 Subject: [PATCH 163/274] fix case --- .../source/{nRF5XPalGattClient.cpp => nRF5xPalGattClient.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/{nRF5XPalGattClient.cpp => nRF5xPalGattClient.cpp} (100%) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalGattClient.cpp similarity index 100% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.cpp rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalGattClient.cpp From fee986750d114ca8376b9a4718b531c3dfe6bc68 Mon Sep 17 00:00:00 2001 From: Paul Szczepanek <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:19:35 +0100 Subject: [PATCH 164/274] fix case --- .../source/{nRF5XPalGattClient.h => nRF5xPalGattClient.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/{nRF5XPalGattClient.h => nRF5xPalGattClient.h} (100%) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalGattClient.h similarity index 100% rename from features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5XPalGattClient.h rename to features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalGattClient.h From b95da8d8c4dc90afaaaa37ae6ea5ca235576dee5 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 9 May 2018 12:27:43 +0100 Subject: [PATCH 165/274] remove crypto when missing ECDH --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp | 3 +++ .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h | 4 ++++ .../TARGET_NRF5/source/nRF5xPalSecurityManager.h | 3 +-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp index 090b29db62..b555b0dc33 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.cpp @@ -24,6 +24,7 @@ #include #include +#if defined(MBEDTLS_ECDH_C) #include "mbedtls/platform.h" #include "mbedtls/ecdh.h" @@ -183,3 +184,5 @@ void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { } // pal } // ble +#endif //defined(MBEDTLS_ECDH_C) + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h index 470002c7e1..35c56a875e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xCrypto.h @@ -25,6 +25,8 @@ #include MBEDTLS_CONFIG_FILE #endif +#if defined(MBEDTLS_ECDH_C) + #include "mbedtls/platform.h" #include "mbedtls/entropy.h" #include "mbedtls/ecp.h" @@ -139,4 +141,6 @@ private: } // pal } // ble +#endif // defined(MBEDTLS_ECDH_C) + #endif // NRF5X_CRYPTO_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h index 8d75a686b0..719d33ebcc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xPalSecurityManager.h @@ -20,9 +20,8 @@ #include "ble/BLETypes.h" #include "ble/pal/PalSecurityManager.h" #include "nrf_ble.h" -#if defined(MBEDTLS_ECDH_C) #include "nRF5xCrypto.h" -#endif + namespace ble { namespace pal { 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 166/274] 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 167/274] 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 168/274] 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 3ca3c2db2c60c3fd71b78746b39425418c804c9d Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Fri, 11 May 2018 18:20:39 +0100 Subject: [PATCH 169/274] Initial implementation of the Security Manager's Privacy feature for Cordio --- .../TARGET_CORDIO/CordioPalSecurityManager.h | 25 ++ .../source/CordioPalSecurityManager.cpp | 239 +++++++++++++++++- 2 files changed, 254 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index d7a0a21cd9..874ea8bc4a 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -322,10 +322,35 @@ public: static bool sm_handler(const wsfMsgHdr_t* msg); private: + struct PrivacyControlBlock; + struct PrivacyClearResListControlBlock; + struct PrivacyAddDevToResListControlBlock; + struct PrivacyRemoveDevFromResListControlBlock; + + void queue_add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ); + + void queue_remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ); + + void queue_clear_resolving_list(); + + void clear_privacy_control_blocks(); + void queue_privacy_control_block(PrivacyControlBlock* block); + void process_privacy_control_blocks(bool cb_completed); + bool _use_default_passkey; passkey_num_t _default_passkey; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; + + PrivacyControlBlock* _pending_privacy_control_blocks; + bool _processing_privacy_control_block; }; } // cordio diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index e121906101..9cc4a45dce 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -22,6 +22,7 @@ #include "att_api.h" #include "smp_api.h" #include "wsf_os.h" +#include "hci_core.h" namespace ble { namespace pal { @@ -33,14 +34,16 @@ CordioSecurityManager::CordioSecurityManager() : _use_default_passkey(false), _default_passkey(0), _lesc_keys_generated(false), - _public_key_x() + _public_key_x(), + _pending_privacy_control_blocks(NULL), + _processing_privacy_control_block(false) { } CordioSecurityManager::~CordioSecurityManager() { - + clear_privacy_control_blocks(); } //////////////////////////////////////////////////////////////////////////// @@ -80,31 +83,57 @@ ble_error_t CordioSecurityManager::reset() uint8_t CordioSecurityManager::read_resolving_list_capacity() { - // FIXME: Implement with privacy support. - return 0; + // The Cordio stack requests this from the controller during initialization + return hciCoreCb.resListSize; } +// As the Cordio stack can only handle one of these methods at a time, we need to create a list of control blocks +// that are dequeued one after the other on completion of the previous one ble_error_t CordioSecurityManager::add_device_to_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address, const irk_t &peer_irk ) { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_add_device_to_resolving_list(peer_identity_address_type, peer_identity_address, peer_irk); + + return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t& peer_identity_address ) { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_remove_device_from_resolving_list(peer_identity_address_type, peer_identity_address); + + return BLE_ERROR_NONE; } ble_error_t CordioSecurityManager::clear_resolving_list() { - // FIXME: Implement with privacy support. - return BLE_ERROR_NOT_IMPLEMENTED; + if( read_resolving_list_capacity() == 0 ) + { + // If 0 is returned as capacity, it means the controller does not support resolving addresses + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // Queue control block + queue_clear_resolving_list(); + + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// @@ -686,11 +715,201 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) { return true; } + // Privacy + case DM_PRIV_ADD_DEV_TO_RES_LIST_IND: // Device added to resolving list + case DM_PRIV_REM_DEV_FROM_RES_LIST_IND: // Device removed from resolving list + case DM_PRIV_CLEAR_RES_LIST_IND: // Resolving list cleared + { + // Previous command completed, we can move to the next control block + self.process_privacy_control_blocks(true); + return true; + } default: return false; } } +struct CordioSecurityManager::PrivacyControlBlock +{ + PrivacyControlBlock() : _next(NULL) {} + + virtual ~PrivacyControlBlock() {} + + virtual void execute() = 0; + + void set_next(PrivacyControlBlock* next) { + _next = next; + } + + PrivacyControlBlock* next() const { + return _next; + } + +private: + PrivacyControlBlock* _next; +}; + +struct CordioSecurityManager::PrivacyClearResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyClearResListControlBlock() : PrivacyControlBlock() + {} + + virtual ~PrivacyClearResListControlBlock() {} + + virtual void execute() { + // Execute command + DmPrivClearResList(); + } +}; + +struct CordioSecurityManager::PrivacyAddDevToResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyAddDevToResListControlBlock( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ) : PrivacyControlBlock(), + _peer_identity_address_type(peer_identity_address_type), + _peer_identity_address(peer_identity_address), + _peer_irk(peer_irk) + {} + + virtual ~PrivacyAddDevToResListControlBlock() {} + + virtual void execute() { + // Check whether we need to enable resolution in LL + bool enable_ll_resolving = DmLlPrivEnabled(); + + // Execute command + DmPrivAddDevToResList(_peer_identity_address_type.value(), _peer_identity_address.data(), _peer_irk.data(), DmSecGetLocalIrk(), enable_ll_resolving, 0); + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; + irk_t _peer_irk; +}; + +struct CordioSecurityManager::PrivacyRemoveDevFromResListControlBlock : CordioSecurityManager::PrivacyControlBlock +{ + PrivacyRemoveDevFromResListControlBlock( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ) : PrivacyControlBlock(), + _peer_identity_address_type(peer_identity_address_type), + _peer_identity_address(peer_identity_address) + { + + } + + virtual ~PrivacyRemoveDevFromResListControlBlock() {} + + virtual void execute() { + // Execute command + DmPrivRemDevFromResList(_peer_identity_address_type.value(), _peer_identity_address.data(), 0); + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; +}; + +// Helper functions for privacy +void CordioSecurityManager::queue_add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk +) +{ + PrivacyAddDevToResListControlBlock* cb = + new (std::nothrow) PrivacyAddDevToResListControlBlock(peer_identity_address_type, peer_identity_address, peer_irk); + if( cb == NULL ) + { + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::queue_remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) +{ + PrivacyRemoveDevFromResListControlBlock* cb = + new (std::nothrow) PrivacyRemoveDevFromResListControlBlock(peer_identity_address_type, peer_identity_address); + if( cb == NULL ) + { + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::queue_clear_resolving_list() { + // Remove any pending control blocks, there's no point executing them as we're about to queue the list + clear_privacy_control_blocks(); + + PrivacyClearResListControlBlock* cb = + new (std::nothrow) PrivacyClearResListControlBlock(); + if( cb == NULL ) + { + return; + } + + queue_privacy_control_block(cb); +} + +void CordioSecurityManager::clear_privacy_control_blocks() { + while(_pending_privacy_control_blocks != NULL) + { + PrivacyControlBlock* next = _pending_privacy_control_blocks->next(); + delete _pending_privacy_control_blocks; + _pending_privacy_control_blocks = next; + } +} + +void CordioSecurityManager::queue_privacy_control_block(PrivacyControlBlock* block) +{ + if( _pending_privacy_control_blocks == NULL ) { + _pending_privacy_control_blocks = block; + } + else { + PrivacyControlBlock* node = _pending_privacy_control_blocks; + while(node->next() != NULL) { + node = node->next(); + } + node->set_next(block); + } + + process_privacy_control_blocks(false); +} + +// Can be called with msg set to NULL +void CordioSecurityManager::process_privacy_control_blocks(bool cb_completed) +{ + if( (_processing_privacy_control_block == true) && !cb_completed ) + { + // Busy, cannot process next control block for now + return; + } + + PrivacyControlBlock* cb = _pending_privacy_control_blocks; + if(cb == NULL) { + // All control blocks processed + _processing_privacy_control_block = false; + return; + } + + // Process next block and free it + _processing_privacy_control_block = true; + + PrivacyControlBlock* next = cb->next(); + cb->execute(); + delete cb; + _pending_privacy_control_blocks = next; +} + } // cordio } // vendor From bcfbeb7f1a5711cce662db0666c6c9ea338c7818 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Fri, 11 May 2018 18:23:33 +0100 Subject: [PATCH 170/274] Some doc adjustments --- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 9cc4a45dce..410287bd5f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -825,6 +825,7 @@ void CordioSecurityManager::queue_add_device_to_resolving_list( new (std::nothrow) PrivacyAddDevToResListControlBlock(peer_identity_address_type, peer_identity_address, peer_irk); if( cb == NULL ) { + // Cannot go further return; } @@ -840,6 +841,7 @@ void CordioSecurityManager::queue_remove_device_from_resolving_list( new (std::nothrow) PrivacyRemoveDevFromResListControlBlock(peer_identity_address_type, peer_identity_address); if( cb == NULL ) { + // Cannot go further return; } @@ -854,6 +856,7 @@ void CordioSecurityManager::queue_clear_resolving_list() { new (std::nothrow) PrivacyClearResListControlBlock(); if( cb == NULL ) { + // Cannot go further return; } @@ -885,7 +888,7 @@ void CordioSecurityManager::queue_privacy_control_block(PrivacyControlBlock* blo process_privacy_control_blocks(false); } -// Can be called with msg set to NULL +// If cb_completed is set to true, it means the previous control block has completed void CordioSecurityManager::process_privacy_control_blocks(bool cb_completed) { if( (_processing_privacy_control_block == true) && !cb_completed ) From 71bd30daf38b530dd4577304fd75761e80674d09 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Fri, 11 May 2018 18:37:02 +0100 Subject: [PATCH 171/274] More inline doc --- .../targets/TARGET_CORDIO/CordioPalSecurityManager.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 874ea8bc4a..98f969ceb3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -327,21 +327,30 @@ private: struct PrivacyAddDevToResListControlBlock; struct PrivacyRemoveDevFromResListControlBlock; + // Queue control block to add device to resolving list void queue_add_device_to_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address, const irk_t &peer_irk ); + // Queue control block to remove device from resolving list void queue_remove_device_from_resolving_list( advertising_peer_address_type_t peer_identity_address_type, const address_t &peer_identity_address ); + // Queue control block to clear resolving list void queue_clear_resolving_list(); + // Clear all control blocks void clear_privacy_control_blocks(); + + // Queue a control block void queue_privacy_control_block(PrivacyControlBlock* block); + + // Try to dequeue and process the next control block + // cb_completed is set when the previous block has completed void process_privacy_control_blocks(bool cb_completed); bool _use_default_passkey; From 40b6813dcf4c89e7c21eb5d9936e92757d032e9e Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Fri, 11 May 2018 18:52:27 +0100 Subject: [PATCH 172/274] Fix wrong use of DmLlPrivEnabled() --- .../targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 410287bd5f..2adb350699 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -778,7 +778,7 @@ struct CordioSecurityManager::PrivacyAddDevToResListControlBlock : CordioSecurit virtual void execute() { // Check whether we need to enable resolution in LL - bool enable_ll_resolving = DmLlPrivEnabled(); + bool enable_ll_resolving = !DmLlPrivEnabled(); // Execute command DmPrivAddDevToResList(_peer_identity_address_type.value(), _peer_identity_address.data(), _peer_irk.data(), DmSecGetLocalIrk(), enable_ll_resolving, 0); 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 173/274] 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 174/274] 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 33c46f56588911f89b64d03698462987ac8caf4f Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 17:49:00 +0100 Subject: [PATCH 175/274] Remove LL resolving 'shorcut' when adding a device to resolving list - this should be controlled by the GAP layer --- .../TARGET_CORDIO/source/CordioPalSecurityManager.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 2adb350699..46df438db8 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -777,11 +777,8 @@ struct CordioSecurityManager::PrivacyAddDevToResListControlBlock : CordioSecurit virtual ~PrivacyAddDevToResListControlBlock() {} virtual void execute() { - // Check whether we need to enable resolution in LL - bool enable_ll_resolving = !DmLlPrivEnabled(); - // Execute command - DmPrivAddDevToResList(_peer_identity_address_type.value(), _peer_identity_address.data(), _peer_irk.data(), DmSecGetLocalIrk(), enable_ll_resolving, 0); + DmPrivAddDevToResList(_peer_identity_address_type.value(), _peer_identity_address.data(), _peer_irk.data(), DmSecGetLocalIrk(), false, 0); } private: From e9ad148db030187891694af1a572ee68264ed06b Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 17:57:27 +0100 Subject: [PATCH 176/274] Added privacy-related methods overrides in GenericGap --- features/FEATURE_BLE/ble/generic/GenericGap.h | 33 +++++++++++++++++++ .../FEATURE_BLE/source/generic/GenericGap.cpp | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index e6b72b6866..93d6ebe65f 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -233,6 +233,39 @@ public: */ virtual ble_error_t initRadioNotification(void); + /** + * @see Gap::enablePrivacy + */ + virtual ble_error_t enablePrivacy(bool enable); + + /** + * @see Gap::setPeripheralPrivacyConfiguration + */ + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::getPeripheralPrivacyConfiguration + */ + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::setCentralPrivacyConfiguration + */ + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + /** + * @see Gap::getCentralPrivacyConfiguration + */ + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); + /** * @see Gap::setAdvertisingData */ diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 19f6667381..fd48e6783c 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -853,6 +853,39 @@ ble_error_t GenericGap::initRadioNotification(void) return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t GenericGap::enablePrivacy(bool enable) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t GenericGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t GenericGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t GenericGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + +ble_error_t GenericGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} + ble_error_t GenericGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) { ble_error_t err = _pal_gap.set_advertising_data( From 7b4a813aca1f83938b459b8c14929998a0820c17 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 18:52:54 +0100 Subject: [PATCH 177/274] Added stubs in GenericGap for privacy configuration methods --- features/FEATURE_BLE/ble/generic/GenericGap.h | 5 +++++ .../FEATURE_BLE/source/generic/GenericGap.cpp | 21 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index 93d6ebe65f..a6f0b2721b 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -348,6 +348,11 @@ private: pal::scanning_filter_policy_t _scanning_filter_policy; pal::advertising_filter_policy_t _advertising_filter_policy; mutable Whitelist_t _whitelist; + + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + mbed::Timeout _advertising_timeout; mbed::Timeout _scan_timeout; pal::ConnectionEventMonitor::EventHandler *_connection_event_handler; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index fd48e6783c..070447bdc0 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -390,6 +390,9 @@ GenericGap::GenericGap( _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), _whitelist(), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), _advertising_timeout(), _scan_timeout(), _connection_event_handler(NULL) @@ -862,28 +865,38 @@ ble_error_t GenericGap::setPeripheralPrivacyConfiguration( const PeripheralPrivacyConfiguration_t *configuration ) { - return BLE_ERROR_NOT_IMPLEMENTED; + _peripheral_privacy_configuration = *configuration; + + + + return BLE_ERROR_NONE; } ble_error_t GenericGap::getPeripheralPrivacyConfiguration( PeripheralPrivacyConfiguration_t *configuration ) { - return BLE_ERROR_NOT_IMPLEMENTED; + *configuration = _peripheral_privacy_configuration; + + return BLE_ERROR_NONE; } ble_error_t GenericGap::setCentralPrivacyConfiguration( const CentralPrivacyConfiguration_t *configuration ) { - return BLE_ERROR_NOT_IMPLEMENTED; + _central_privacy_configuration = *configuration; + + return BLE_ERROR_NONE; } ble_error_t GenericGap::getCentralPrivacyConfiguration( CentralPrivacyConfiguration_t *configuration ) { - return BLE_ERROR_NOT_IMPLEMENTED; + *configuration = _central_privacy_configuration; + + return BLE_ERROR_NONE; } ble_error_t GenericGap::setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) From 5734fca195586f418756f09faefdd3d894c01818 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 18:53:23 +0100 Subject: [PATCH 178/274] Added set_address_resolution method in GAP Pal with Cordio implementation --- features/FEATURE_BLE/ble/pal/PalGap.h | 13 +++++++++++++ .../targets/TARGET_CORDIO/CordioPalGap.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index b365e5c23b..d83e532dba 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -649,6 +649,19 @@ struct Gap { disconnection_reason_t disconnection_reason ) = 0; + /** Enable or disable private addresses resolution + * + * @param enable whether to enable private addresses resolution + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable Command command. + */ + virtual ble_error_t set_address_resolution( + bool enable + ) = 0; + /** * Register a callback which will handle Gap events. * diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 69ca5e9848..7a586add9f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -308,6 +308,13 @@ public: return BLE_ERROR_NONE; } + virtual ble_error_t set_address_resolution( + bool enable + ) { + DmPrivSetAddrResEnable(enable); + return BLE_ERROR_NONE; + } + // singleton of the ARM Cordio client static Gap& get_gap() { static Gap _gap; From cf03d40909a52ed35b0dcb606959e33913c3ebbb Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 18:54:11 +0100 Subject: [PATCH 179/274] Doc fix in PalGap.h --- features/FEATURE_BLE/ble/pal/PalGap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index d83e532dba..8168f9404d 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -656,7 +656,7 @@ struct Gap { * @return BLE_ERROR_NONE if the request has been successfully sent or the * appropriate error otherwise. * - * @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable Command command. + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable command. */ virtual ble_error_t set_address_resolution( bool enable From 4c5e2a8094597975c96beb94d91f154994c3b0fa Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 19:14:56 +0100 Subject: [PATCH 180/274] Added method to update resolution settings in GenericGap --- features/FEATURE_BLE/ble/generic/GenericGap.h | 2 ++ .../FEATURE_BLE/source/generic/GenericGap.cpp | 24 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index a6f0b2721b..fb3ecb4042 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -339,6 +339,8 @@ private: bool initialize_whitelist() const; + ble_error_t update_address_resolution_setting(); + pal::EventQueue& _event_queue; pal::Gap &_pal_gap; pal::GenericAccessService &_gap_service; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 070447bdc0..fb2d7593ce 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -858,7 +858,9 @@ ble_error_t GenericGap::initRadioNotification(void) ble_error_t GenericGap::enablePrivacy(bool enable) { - return BLE_ERROR_NOT_IMPLEMENTED; + update_address_resolution_setting(); + + return BLE_ERROR_NONE; } ble_error_t GenericGap::setPeripheralPrivacyConfiguration( @@ -867,7 +869,7 @@ ble_error_t GenericGap::setPeripheralPrivacyConfiguration( { _peripheral_privacy_configuration = *configuration; - + update_address_resolution_setting(); return BLE_ERROR_NONE; } @@ -887,6 +889,8 @@ ble_error_t GenericGap::setCentralPrivacyConfiguration( { _central_privacy_configuration = *configuration; + update_address_resolution_setting(); + return BLE_ERROR_NONE; } @@ -1212,6 +1216,22 @@ bool GenericGap::initialize_whitelist() const return true; } +ble_error_t update_address_resolution_setting() +{ + // Only disable if privacy is disabled or resolution is not requested in either central or peripheral mode + bool enable = true; + + if(!_privacy_enabled) { + enable = false; + } + else if( (_peripheral_privacy_configuration.resolution_strategy == DO_NOT_RESOLVE) + && (_central_privacy_configuration.resolution_strategy == DO_NOT_RESOLVE) ) { + enable = false; + } + + return _pal_gap.set_address_resolution(enable); +} + void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) { _connection_event_handler = connection_event_handler; From 1a623e6670aec821965d8404c166dcdb397901de Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 19:15:20 +0100 Subject: [PATCH 181/274] Added method to enable/disable privacy in GAP Pal with Cordio impl --- features/FEATURE_BLE/ble/pal/PalGap.h | 12 ++++++++++++ .../FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 8168f9404d..5f7865d8f2 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -649,6 +649,18 @@ struct Gap { disconnection_reason_t disconnection_reason ) = 0; + /** Enable or disable privacy feature + * @param enable whether to enable privacy feature + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature. + */ + virtual ble_error_t set_privacy( + bool enable + ) = 0; + /** Enable or disable private addresses resolution * * @param enable whether to enable private addresses resolution diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 7a586add9f..cc6cdce54b 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -308,6 +308,17 @@ public: return BLE_ERROR_NONE; } + virtual ble_error_t set_privacy( + bool enable + ) { + if(enable) { + DmDevPrivStart(15 * 60); // Use 15 minutes renewal timer as mandated by the BLE Spec + } else { + DmDevPrivStop(); + } + return BLE_ERROR_NONE; + } + virtual ble_error_t set_address_resolution( bool enable ) { From 2509a88d58d04aff46ac96699d55752109bc02a6 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 20:37:14 +0100 Subject: [PATCH 182/274] Revert set_privacy() in Cordio GAP PAL impl --- features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index cc6cdce54b..38a482bd74 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -311,11 +311,6 @@ public: virtual ble_error_t set_privacy( bool enable ) { - if(enable) { - DmDevPrivStart(15 * 60); // Use 15 minutes renewal timer as mandated by the BLE Spec - } else { - DmDevPrivStop(); - } return BLE_ERROR_NONE; } From 620ebc3f9a54c4dfa6baf413c8f2ea075d30e5aa Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 20:38:29 +0100 Subject: [PATCH 183/274] Some fixes in GenericGap --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index fb2d7593ce..31fcad15c6 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -858,6 +858,10 @@ ble_error_t GenericGap::initRadioNotification(void) ble_error_t GenericGap::enablePrivacy(bool enable) { + _privacy_enabled = enable; + + _pal_gap.set_privacy(enable); + update_address_resolution_setting(); return BLE_ERROR_NONE; @@ -1216,7 +1220,7 @@ bool GenericGap::initialize_whitelist() const return true; } -ble_error_t update_address_resolution_setting() +ble_error_t GenericGap::update_address_resolution_setting() { // Only disable if privacy is disabled or resolution is not requested in either central or peripheral mode bool enable = true; @@ -1224,8 +1228,8 @@ ble_error_t update_address_resolution_setting() if(!_privacy_enabled) { enable = false; } - else if( (_peripheral_privacy_configuration.resolution_strategy == DO_NOT_RESOLVE) - && (_central_privacy_configuration.resolution_strategy == DO_NOT_RESOLVE) ) { + else if( (_peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) + && (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) ) { enable = false; } From 6a2ffaeac07735b023a893b027fa453c92ccba57 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 22:16:08 +0100 Subject: [PATCH 184/274] Update own address type generation in GenericGap --- features/FEATURE_BLE/ble/generic/GenericGap.h | 2 +- .../FEATURE_BLE/source/generic/GenericGap.cpp | 31 ++++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index fb3ecb4042..d3034b504d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -335,7 +335,7 @@ private: void on_unexpected_error(const pal::GapUnexpectedErrorEvent &e); - pal::own_address_type_t get_own_address_type(); + pal::own_address_type_t get_own_address_type(bool central_not_peripheral, bool non_connectable_or_scan_request); bool initialize_whitelist() const; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 31fcad15c6..f1c5cc6b3d 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -533,7 +533,7 @@ ble_error_t GenericGap::connect( _initiator_policy_mode, (pal::connection_peer_address_type_t::type) peerAddrType, ble::address_t(peerAddr), - get_own_address_type(), + get_own_address_type(true /* central */, false /* requires resolvable address */), connectionParams->minConnectionInterval, connectionParams->maxConnectionInterval, connectionParams->slaveLatency, @@ -825,7 +825,7 @@ ble_error_t GenericGap::startRadioScan(const GapScanningParams &scanningParams) scanningParams.getActiveScanning(), scanningParams.getInterval(), scanningParams.getWindow(), - get_own_address_type(), + get_own_address_type(true /* central */, true /* can use non resolvable address for scan requests */), _scanning_filter_policy ); @@ -939,7 +939,8 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) /* advertising_interval_min */ params.getIntervalInADVUnits(), /* advertising_interval_max */ params.getIntervalInADVUnits(), (pal::advertising_type_t::type) params.getAdvertisingType(), - get_own_address_type(), + get_own_address_type(false /* peripheral */, + params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED /* we can only use non resolvable addresses int this case */), pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, ble::address_t(), pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, @@ -1186,14 +1187,34 @@ void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) // has been updated. } -pal::own_address_type_t GenericGap::get_own_address_type() +pal::own_address_type_t GenericGap::get_own_address_type(bool central_not_peripheral, bool non_connectable_or_scan_request) { + if(_privacy_enabled) { + bool can_use_non_resolvable_address = false; + if(central_not_peripheral) { + can_use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; + } else { + can_use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; + } + + // An non resolvable private address should be generated + if(non_connectable_or_scan_request && can_use_non_resolvable_address) { + return pal::own_address_type_t::RANDOM_ADDRESS; + } + + switch (_address_type) { + case BLEProtocol::AddressType::PUBLIC: + return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_PUBLIC_FALLBACK; + default: + return pal::own_address_type_t::RESOLVABLE_PRIVATE_ADDRESS_RANDOM_FALLBACK; + } + } + switch (_address_type) { case BLEProtocol::AddressType::PUBLIC: return pal::own_address_type_t::PUBLIC_ADDRESS; default: return pal::own_address_type_t::RANDOM_ADDRESS; - // FIXME: Handle case when privacy is used. } } From 926efa40181190014b4bf5bc5503a7f90c99d40e Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 22:37:59 +0100 Subject: [PATCH 185/274] Filter out advertising reports for unresolved addresses if required --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index f1c5cc6b3d..9d58e739b8 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -1093,6 +1093,16 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) for (size_t i = 0; i < e.size(); ++i) { pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; + // Check if the address hasn't been resolved + if(_central_privacy_configuration.resolution_strategy == ResolutionStrategy::RESOLVE_AND_FILTER) + { + if(advertising.address_type == connection_peer_address_type_t::RANDOM_ADDRESS) + { + // Filter it out + continue; + } + } + processAdvertisementReport( advertising.address.data(), advertising.rssi, From 21471bb3c9a85488cf1d22197e24f090c4b97e4d Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 22:42:11 +0100 Subject: [PATCH 186/274] and make sure it compiles and that policy is only applied if privacy is enabled :) --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 9d58e739b8..356a25ac27 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -1094,9 +1094,9 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; // Check if the address hasn't been resolved - if(_central_privacy_configuration.resolution_strategy == ResolutionStrategy::RESOLVE_AND_FILTER) + if(_privacy_enabled && _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER) { - if(advertising.address_type == connection_peer_address_type_t::RANDOM_ADDRESS) + if(advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS) { // Filter it out continue; 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 187/274] 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 69e35c49c8c063d8e9f6a9e10ced08cd6a701c17 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Sun, 13 May 2018 23:25:52 +0100 Subject: [PATCH 188/274] Handle resolution policy for peripheral in GenericGap --- .../FEATURE_BLE/source/generic/GenericGap.cpp | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 356a25ac27..cbc430538a 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -17,6 +17,7 @@ #include #include +#include "ble/BLEInstanceBase.h" #include "ble/BLEProtocol.h" #include "ble/Gap.h" #include "ble/pal/PalGap.h" @@ -1120,6 +1121,37 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e // TODO: deprecate ownAddrType and ownAddr, those are not specified // from the Bluetooth perspective if (e.status == pal::hci_error_code_t::SUCCESS) { + bool needs_pairing = false; + bool needs_authentication = false; + + if(_privacy_enabled && (e.role.value() == e.role.SLAVE)) { + // Apply privacy policy if in peripheral mode for non-resolved addresses + RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); + ble_error_t ret = getRandomAddressType(e.peer_address.data(), &random_address_type); + if((ret != BLE_ERROR_NONE) + || (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE)) + { + switch(_peripheral_privacy_configuration.resolution_strategy) + { + case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: + // Reject connection request - the user will get notified through a callback + _pal_gap.disconnect(e.connection_handle, pal::disconnection_reason_t::AUTHENTICATION_FAILLURE); + return; + + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + needs_pairing = true; + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + needs_authentication = true; + break; + + default: + break; + } + } + } + if (e.role.value() == e.role.SLAVE) { _advertising_timeout.detach(); _pal_gap.advertising_enable(false); @@ -1149,7 +1181,17 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e address.data(), &connection_params ); - } else { + + // Now starts pairing or authentication procedures if required + if(needs_pairing) { + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + sm.requestPairing(e.connection_handle); + } + else if(needs_authentication) { + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + sm.requestAuthentication(e.connection_handle); + } + } else { // for now notify user that the connection failled by issuing a timeout // event 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 189/274] 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 190/274] 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 191/274] 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 192/274] 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 193/274] 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 194/274] 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 a3d9d6cebd805653205302241255f6262ad6a834 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:26:39 +0100 Subject: [PATCH 195/274] Business logic for handling non-resolvable private addresses --- features/FEATURE_BLE/ble/generic/GenericGap.h | 9 ++ .../FEATURE_BLE/source/generic/GenericGap.cpp | 98 ++++++++++++++++++- .../targets/TARGET_CORDIO/CordioPalGap.h | 4 + 3 files changed, 108 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index d3034b504d..3c34a9734a 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -341,6 +341,12 @@ private: ble_error_t update_address_resolution_setting(); + void set_random_address_rotation(bool enable); + + void update_random_address(); + + void on_address_rotation_timeout(); + pal::EventQueue& _event_queue; pal::Gap &_pal_gap; pal::GenericAccessService &_gap_service; @@ -354,9 +360,12 @@ private: bool _privacy_enabled; PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; CentralPrivacyConfiguration_t _central_privacy_configuration; + ble::address_t _random_static_identity_address; + bool _random_address_rotating; mbed::Timeout _advertising_timeout; mbed::Timeout _scan_timeout; + mbed::Ticker _address_rotation_ticker; pal::ConnectionEventMonitor::EventHandler *_connection_event_handler; }; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index cbc430538a..21fed40982 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -401,6 +401,9 @@ GenericGap::GenericGap( _pal_gap.when_gap_event_received( mbed::callback(this, &GenericGap::on_gap_event_received) ); + + // Recover static random identity + _random_static_identity_address = _pal_gap.get_random_address(); } GenericGap::~GenericGap() @@ -432,6 +435,7 @@ ble_error_t GenericGap::setAddress( _address_type = BLEProtocol::AddressType::RANDOM; _address = ble::address_t(address); + _random_static_identity_address = ble::address_t(address); return BLE_ERROR_NONE; } @@ -487,6 +491,10 @@ ble_error_t GenericGap::stopAdvertising() } _advertising_timeout.detach(); state.advertising = false; + + // Stop address rotation if required + set_random_address_rotation(false); + return BLE_ERROR_NONE; } @@ -497,6 +505,9 @@ ble_error_t GenericGap::stopScan() return err; } + // Stop address rotation if required + set_random_address_rotation(false); + _scan_timeout.detach(); return BLE_ERROR_NONE; } @@ -822,11 +833,19 @@ ble_error_t GenericGap::startRadioScan(const GapScanningParams &scanningParams) return BLE_ERROR_INVALID_STATE; } + pal::own_address_type_t own_address_type = get_own_address_type(true /* central */, true /* can use non resolvable address for scan requests */); + + if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) + { + // Use non-resolvable static random address + set_random_address_rotation(true); + } + ble_error_t err = _pal_gap.set_scan_parameters( scanningParams.getActiveScanning(), scanningParams.getInterval(), scanningParams.getWindow(), - get_own_address_type(true /* central */, true /* can use non resolvable address for scan requests */), + own_address_type, _scanning_filter_policy ); @@ -930,6 +949,15 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) return BLE_ERROR_INVALID_PARAM; } + pal::own_address_type_t own_address_type = get_own_address_type(false /* peripheral */, + params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED /* we can only use non resolvable addresses int this case */); + + if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) + { + // Use non-resolvable static random address + set_random_address_rotation(true); + } + // TODO: fix the high level API to have a min/max range // Going against recommendations (The Advertising_Interval_Min and // Advertising_Interval_Max should not be the same value to enable the @@ -940,8 +968,7 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) /* advertising_interval_min */ params.getIntervalInADVUnits(), /* advertising_interval_max */ params.getIntervalInADVUnits(), (pal::advertising_type_t::type) params.getAdvertisingType(), - get_own_address_type(false /* peripheral */, - params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED /* we can only use non resolvable addresses int this case */), + own_address_type, pal::advertising_peer_address_type_t::PUBLIC_ADDRESS, ble::address_t(), pal::advertising_channel_map_t::ALL_ADVERTISING_CHANNELS, @@ -1054,6 +1081,10 @@ void GenericGap::process_advertising_timeout() if (err) { // TODO: define the mechanism signaling the error } + + // Stop address rotation if required + set_random_address_rotation(false); + processTimeoutEvent(Gap::TIMEOUT_SRC_ADVERTISING); } @@ -1155,6 +1186,9 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e if (e.role.value() == e.role.SLAVE) { _advertising_timeout.detach(); _pal_gap.advertising_enable(false); + + // Stop address rotation if required + set_random_address_rotation(false); } // using these parameters if stupid, there is no range for the @@ -1309,6 +1343,64 @@ ble_error_t GenericGap::update_address_resolution_setting() return _pal_gap.set_address_resolution(enable); } +void GenericGap::set_random_address_rotation(bool enable) +{ + if(enable == _random_address_rotating) { + return; + } + + _random_address_rotating = enable; + + if(enable) { + // Set first address + update_random_address(); + + // Schedule rotations every 15 minutes as recomended by the spec + _address_rotation_ticker.attach_us( + mbed::callback(this, &GenericGap::on_address_rotation_timeout), + 15 * 60 * 1000000U + ); + } + else { + // Stop ticker + _address_rotation_ticker.detach(); + + // Set static random identity address + _pal_gap.set_random_address( + _random_static_identity_address + ); + } +} + +void GenericGap::update_random_address() +{ + ble::address_t address; + + if(!_random_address_rotating) + { + // This event might have been queued before we disabled address rotation + return; + } + + // TODO: Placeholder: Get random data + // Build a non-resolvable private address + + ble_error_t err = _pal_gap.set_random_address( + address + ); + if (err) { + return; + } + + _address_type = BLEProtocol::AddressType::RANDOM; + _address = address; +} + +void GenericGap::on_address_rotation_timeout() +{ + _event_queue.post(mbed::callback(this, &GenericGap::update_random_address)); +} + void GenericGap::set_connection_event_handler(pal::ConnectionEventMonitor::EventHandler *connection_event_handler) { _connection_event_handler = connection_event_handler; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index 38a482bd74..bb41b19b2c 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -311,6 +311,9 @@ public: virtual ble_error_t set_privacy( bool enable ) { + // + + return BLE_ERROR_NONE; } @@ -478,6 +481,7 @@ private: }; private: + address_t device_random_static_identity_address; address_t device_random_address; bool use_active_scanning; }; From 472d3de84912fd33e8fb5c4cdc37d76a4c9c4419 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:36:02 +0100 Subject: [PATCH 196/274] Give GenericGap access to the Security Manager's PAL --- features/FEATURE_BLE/ble/generic/GenericGap.h | 8 +++++++- features/FEATURE_BLE/source/generic/GenericGap.cpp | 4 +++- .../targets/TARGET_CORDIO/source/CordioBLE.cpp | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index 3c34a9734a..d18814adc7 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -23,6 +23,7 @@ #include "ble/BLEProtocol.h" #include "ble/Gap.h" #include "ble/pal/PalGap.h" +#include "ble/pal/PalSecurityManager.h" #include "ble/pal/GapEvents.h" #include "ble/pal/GapTypes.h" #include "ble/BLETypes.h" @@ -55,11 +56,15 @@ public: * * @param generic_access_service Platform abstraction instance managing * the GATT generic access service. + * + * @param pal_sm Security Manager Platform abstraction instance containing the base + * Security Manager primitives. */ GenericGap( pal::EventQueue &event_queue, pal::Gap &pal_gap, - pal::GenericAccessService &generic_access_service + pal::GenericAccessService &generic_access_service, + pal::SecurityManager &pal_sm ); /** @@ -350,6 +355,7 @@ private: pal::EventQueue& _event_queue; pal::Gap &_pal_gap; pal::GenericAccessService &_gap_service; + pal::SecurityManager &_pal_sm; BLEProtocol::AddressType_t _address_type; ble::address_t _address; pal::initiator_policy_t _initiator_policy_mode; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 21fed40982..9ada111b3b 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -382,10 +382,12 @@ static bool is_advertising_params_valid(const GapAdvertisingParams& params) GenericGap::GenericGap( pal::EventQueue& event_queue, pal::Gap& pal_gap, - pal::GenericAccessService& generic_access_service + pal::GenericAccessService& generic_access_service, + pal::SecurityManager& pal_sm ) : _event_queue(event_queue), _pal_gap(pal_gap), _gap_service(generic_access_service), + _pal_sm(pal_sm), _address_type(BLEProtocol::AddressType::PUBLIC), _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER), _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 46ec738a0e..48b7d0724f 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -170,7 +170,8 @@ generic::GenericGap& BLE::getGap() static ble::generic::GenericGap gap( _event_queue, pal::vendor::cordio::Gap::get_gap(), - cordio_gap_service + cordio_gap_service, + pal::vendor::cordio::CordioSecurityManager::get_security_manager() ); return gap; From 3523cdb264c124cf4d353f9bd9d8cdb27da3b6c2 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:37:37 +0100 Subject: [PATCH 197/274] Missing initializer in GenericGap --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 9ada111b3b..25657f02d5 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -394,6 +394,7 @@ GenericGap::GenericGap( _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), _whitelist(), _privacy_enabled(false), + _random_address_rotating(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), _advertising_timeout(), From 67ec6323fcadee94216cf1c2dd288901a3ba0163 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:52:29 +0100 Subject: [PATCH 198/274] Added update_random_address() implementation in GenericGap --- .../FEATURE_BLE/source/generic/GenericGap.cpp | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 25657f02d5..9856d601c5 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -1377,16 +1377,40 @@ void GenericGap::set_random_address_rotation(bool enable) void GenericGap::update_random_address() { - ble::address_t address; - if(!_random_address_rotating) { // This event might have been queued before we disabled address rotation return; } - // TODO: Placeholder: Get random data - // Build a non-resolvable private address + ble::address_t address; + + do { + byte_array_t<8> random_data; + + ble_error_t ret = _pal_sm.get_random_data(random_data); + if (ret != BLE_ERROR_NONE) { + // Abort + return; + } + + // Build a non-resolvable private address as specified in the Core 4.2 spec, Vol 6, Part B, 1.3.2.2 + // Mask out two MSbs + random_data[5] &= 0x3F; + + // Copy to address - will copy first 6 bytes + address = ble::address_t(random_data.data()); + + if(!is_random_private_non_resolvable_address(address.data())) + { + // If address is invalid, which is unlikely (all 0s or all 1s), try again + // If implementation is faulty, we'll get stuck here + continue; + } + + // Address is valid + break; + } while(true); ble_error_t err = _pal_gap.set_random_address( address From d8b63fc03d39d6501623ce41d45ce04dacd2158e Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:53:15 +0100 Subject: [PATCH 199/274] Reordered initializers in GenericGap --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 9856d601c5..af9debd331 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -394,9 +394,9 @@ GenericGap::GenericGap( _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), _whitelist(), _privacy_enabled(false), - _random_address_rotating(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), + _random_address_rotating(false), _advertising_timeout(), _scan_timeout(), _connection_event_handler(NULL) From 6c6af1b0d5fde8731327a06af426083b55089f20 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Mon, 14 May 2018 13:59:32 +0100 Subject: [PATCH 200/274] Added missing masks and fixed bit ordering in is_random_xx_address() functions --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index af9debd331..59f315bfb0 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -229,8 +229,8 @@ static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address) */ static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) { - // top two msb bits shall be equal to 1. - if ((address[5] >> 6) != 0x03) { + // top two msb bits shall be equal to 0b11. + if (((address[5] >> 6) & 0xC0) != 0xC0) { return false; } @@ -243,8 +243,8 @@ static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) static bool is_random_private_non_resolvable_address( const BLEProtocol::AddressBytes_t address ) { - // top two msb bits shall be equal to 0. - if ((address[5] >> 6) != 0x00) { + // top two msb bits shall be equal to 0b00. + if (((address[5] >> 6) & 0xC0) != 0x00) { return false; } @@ -257,8 +257,8 @@ static bool is_random_private_non_resolvable_address( static bool is_random_private_resolvable_address( const BLEProtocol::AddressBytes_t address ) { - // top two msb bits shall be equal to 01. - if ((address[5] >> 6) != 0x01) { + // top two msb bits shall be equal to 0b01. + if (((address[5] >> 6) & 0xC0) != 0x40) { return false; } 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 201/274] 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 202/274] 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 2860365a3c77c075f388f836575fc884df41a7cd Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 12:16:51 +0100 Subject: [PATCH 203/274] BLE: Improve readibility of condition. --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 03f5450d43..8e4effaa90 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -448,8 +448,8 @@ ble_error_t GenericSecurityManager::setLinkEncryption( } else if (encryption == link_encryption_t::ENCRYPTED_WITH_SC_AND_MITM) { if (cb->ltk_mitm_protected && - cb->secure_connections_paired && ! - cb->encrypted + cb->secure_connections_paired && + !cb->encrypted ) { cb->encryption_requested = true; return enable_encryption(connection); From 2c7ed993ecf36ac15f3f40a95e8d0f57481c6b88 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 12:17:34 +0100 Subject: [PATCH 204/274] BLE: Fix security requirements in GattCharacteristic. --- features/FEATURE_BLE/ble/GattCharacteristic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 526e0fad39..3717d560b9 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -1412,7 +1412,7 @@ public: writeAuthorizationCallback(), _update_security(SecurityRequirement_t::NONE) { _valueAttribute.allowWrite(isWritable(_properties)); - _valueAttribute.allowWrite(isReadable(_properties)); + _valueAttribute.allowRead(isReadable(_properties)); if (_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) { _valueAttribute.setWriteSecurityRequirement( From ee720f30bb753321b29beef1d92e84e770af38ac Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 12:17:59 +0100 Subject: [PATCH 205/274] BLE: Comment security requirement elevation for signed writes. --- features/FEATURE_BLE/ble/GattCharacteristic.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/features/FEATURE_BLE/ble/GattCharacteristic.h b/features/FEATURE_BLE/ble/GattCharacteristic.h index 3717d560b9..2f0754b051 100644 --- a/features/FEATURE_BLE/ble/GattCharacteristic.h +++ b/features/FEATURE_BLE/ble/GattCharacteristic.h @@ -1414,6 +1414,8 @@ public: _valueAttribute.allowWrite(isWritable(_properties)); _valueAttribute.allowRead(isReadable(_properties)); + // signed writes requires at least an unauthenticated CSRK or an + // unauthenticated ltk if the link is encrypted. if (_properties & BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES) { _valueAttribute.setWriteSecurityRequirement( SecurityRequirement_t::UNAUTHENTICATED From 4acb3937e44693fbe16f6d398468afa496d9f7ee Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 14:32:29 +0100 Subject: [PATCH 206/274] Cordio BLE: Fix potential memory leak in GattServer. --- .../targets/TARGET_CORDIO/source/CordioGattServer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp index 0d6b73376d..41568ab5f3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioGattServer.cpp @@ -84,6 +84,7 @@ ble_error_t GattServer::addService(GattService &service) att_service->attGroup.pAttr = (attsAttr_t*) alloc_block(attributes_count * sizeof(attsAttr_t)); if (att_service->attGroup.pAttr == NULL) { + delete att_service; return BLE_ERROR_BUFFER_OVERFLOW; } From f7f1272647ed5776eb77986bdad67b66e3d3f6e6 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 11 May 2018 11:42:42 +0100 Subject: [PATCH 207/274] Nordic: Backport security manager pal for NRF5X targets. --- .../TARGET_NRF5x/source/nRF5xCrypto.cpp | 188 +++ .../TARGET_NRF5x/source/nRF5xCrypto.h | 146 ++ .../source/nRF5xPalSecurityManager.cpp | 1225 +++++++++++++++++ .../source/nRF5xPalSecurityManager.h | 403 ++++++ 4 files changed, 1962 insertions(+) create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.h create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp create mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.cpp new file mode 100644 index 0000000000..b555b0dc33 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.cpp @@ -0,0 +1,188 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include +#include + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "platform/CriticalSectionLock.h" +#include "ble/BLETypes.h" +#include "cmsis.h" +#include "nRF5xCrypto.h" +#include "platform/mbed_assert.h" +#include "nrf_soc.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +CryptoToolbox::CryptoToolbox() : _initialized(false) { + mbedtls_entropy_init(&_entropy_context); + mbedtls_ecp_group_init(&_group); + int err = mbedtls_ecp_group_load( + &_group, + MBEDTLS_ECP_DP_SECP256R1 + ); + _initialized = err ? false : true; +} + +CryptoToolbox::~CryptoToolbox() { + mbedtls_ecp_group_free(&_group); + mbedtls_entropy_free(&_entropy_context); +} + +bool CryptoToolbox::generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret +) { + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + int err = mbedtls_ecp_gen_keypair( + &_group, + &secret_key, + &public_keys, + mbedtls_entropy_func, + &_entropy_context + ); + + if (!err) { + store_mpi(secret, secret_key); + store_mpi(X, public_keys.X); + store_mpi(Y, public_keys.Y); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + + return err ? false : true; +} + +bool CryptoToolbox::generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret +) { + mbedtls_mpi result; + mbedtls_mpi secret_key; + mbedtls_ecp_point public_keys; + + mbedtls_mpi_init(&result); + mbedtls_mpi_init(&secret_key); + mbedtls_ecp_point_init(&public_keys); + + load_mpi(secret_key, own_secret); + load_mpi(public_keys.X, peer_X); + load_mpi(public_keys.Y, peer_Y); + mbedtls_mpi_lset( &public_keys.Z, 1 ); + + int err = mbedtls_ecdh_compute_shared( + &_group, + &result, + &public_keys, + &secret_key, + /* rng function; optional */ NULL, + /* rng param */ NULL + ); + + if (!err) { + store_mpi(shared_secret, result); + } + + mbedtls_ecp_point_free(&public_keys); + mbedtls_mpi_free(&secret_key); + mbedtls_mpi_free(&result); + + return err ? false : true; +} + +bool CryptoToolbox::ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash +) { + // Note copy then swap operation can be optimized. + + // Note: the encryption block works in big endian; go figure. + nrf_ecb_hal_data_t ecb_hal_data; + + memcpy(ecb_hal_data.key, irk.data(), irk.size()); + swap_endian(ecb_hal_data.key, sizeof(ecb_hal_data.key)); + + memcpy(ecb_hal_data.cleartext, prand.data(), prand.size()); + memset(ecb_hal_data.cleartext + prand.size(), 0, sizeof(ecb_hal_data.cleartext) - prand.size()); + swap_endian(ecb_hal_data.cleartext, sizeof(ecb_hal_data.cleartext)); + + uint32_t err = sd_ecb_block_encrypt(&ecb_hal_data); + + if (err) { + return false; + } + + swap_endian(ecb_hal_data.ciphertext, sizeof(ecb_hal_data.ciphertext)); + + memcpy(hash.data(), ecb_hal_data.ciphertext, hash.size()); + + return true; +} + + +void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { + ble::public_key_coord_t src_be = src.data(); + swap_endian(src_be.data(), src_be.size()); + mbedtls_mpi_read_binary(&dest, src_be.data(), src_be.size()); +} + +void CryptoToolbox::store_mpi(ArrayView& dest, const mbedtls_mpi& src) { + mbedtls_mpi_write_binary(&src, dest.data(), dest.size()); + swap_endian(dest.data(), dest.size()); +} + +void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { + for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { + std::swap(buf[low], buf[high]); + } +} + +} // nordic +} // vendor +} // pal +} // ble + +#endif //defined(MBEDTLS_ECDH_C) + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.h new file mode 100644 index 0000000000..35c56a875e --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xCrypto.h @@ -0,0 +1,146 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 NRF5X_CRYPTO_ +#define NRF5X_CRYPTO_ + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/platform.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ecp.h" + +#include "platform/NonCopyable.h" +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +/** + * Toolbox of cryptographic functions used in BLE. + */ +class CryptoToolbox : mbed::NonCopyable { + +public: + /** + * Size of the Key used in lesc crypto operations. + */ + static const ptrdiff_t lesc_key_size_ = public_key_coord_t::size_; + + /** + * Size of an IRK. + */ + static const ptrdiff_t irk_size_ = irk_t::size_; + + /** + * Size of the hash generated by ah. + */ + static const ptrdiff_t hash_size_ = 3; + + /** + * Size of prand. + */ + static const ptrdiff_t prand_size_ = 3; + + /** + * Create a new CryptoToolbox. + */ + CryptoToolbox(); + + /** + * Destroy a CryptoTioolbox object. + */ + ~CryptoToolbox(); + + /** + * Generate lesc public and private keys. + * @param[out] X The component X of the public key. + * @param[out] Y The component Y of the public key. + * @param[out] secret The secret key. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_keys( + ArrayView X, + ArrayView Y, + ArrayView secret + ); + + /** + * Generate a shared secret from a peer public key and a local secret key. + * @param[in] peer_X The component X of the peer public key. + * @param[in] peer_Y The component Y of the peer public key. + * @param[in] own_secret The local secret key. + * @param[out] shared_secret The shared secret generated. + * @return true if the shared secret has been successfully generated and + * false otherwise. + */ + bool generate_shared_secret( + const ArrayView& peer_X, + const ArrayView& peer_Y, + const ArrayView& own_secret, + ArrayView shared_secret + ); + + /** + * Execute the function ah. This function can be used to generate private + * resolvable addresses and resolve them. + * + * @note all parameters passed and return by this fucntion are in little + * endian. + * + * @param[in] irk The key used to create hash. + * @param[in] prand The random part from which the hash will be generated. + * @param[out] hash The hash generated. + * + * @return true in case of success and false otherwise. + */ + bool ah( + const ArrayView& irk, + const ArrayView& prand, + ArrayView hash + ); + +private: + void load_mpi(mbedtls_mpi& dest, const ArrayView& src); + + void store_mpi(ArrayView& dest, const mbedtls_mpi& src); + + void swap_endian(uint8_t* buf, size_t len); + + bool _initialized; + mbedtls_entropy_context _entropy_context; + mbedtls_ecp_group _group; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif // defined(MBEDTLS_ECDH_C) + +#endif // NRF5X_CRYPTO_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp new file mode 100644 index 0000000000..0be03868c6 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp @@ -0,0 +1,1225 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 +#include "nRF5xPalSecurityManager.h" +#include "nrf_ble.h" +#include "ble_gap.h" +#include "nrf_soc.h" +#include "nrf_error.h" + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +namespace { +static ble_error_t convert_sd_error(uint32_t err) { + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case NRF_ERROR_INVALID_PARAM: + case BLE_ERROR_INVALID_CONN_HANDLE: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_INVALID_STATE: + case BLE_ERROR_INVALID_ROLE: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NOT_SUPPORTED: + return BLE_ERROR_NOT_IMPLEMENTED; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_TIMEOUT: + return BLE_ERROR_INVALID_STATE; + case NRF_ERROR_NO_MEM: + return BLE_ERROR_NO_MEM; + default: + return BLE_ERROR_UNSPECIFIED; + } +} +} + +enum pairing_role_t { + PAIRING_INITIATOR, + PAIRING_RESPONDER +}; + +struct nRF5xSecurityManager::pairing_control_block_t { + pairing_control_block_t* next; + connection_handle_t connection; + pairing_role_t role; + + // flags of the key present + KeyDistribution initiator_dist; + KeyDistribution responder_dist; + + // own keys + ble_gap_enc_key_t own_enc_key; + ble_gap_id_key_t own_id_key; + ble_gap_sign_info_t own_sign_key; + ble_gap_lesc_p256_pk_t own_pk; + + // peer keys + ble_gap_enc_key_t peer_enc_key; + ble_gap_id_key_t peer_id_key; + ble_gap_sign_info_t peer_sign_key; + ble_gap_lesc_p256_pk_t peer_pk; + + // flag required to help DHKey computation/process; should be removed with + // later versions of the softdevice + uint8_t own_oob:1; + uint8_t peer_oob:1; +}; + +nRF5xSecurityManager::nRF5xSecurityManager() + : ::ble::pal::SecurityManager(), + _sign_counter(), + _io_capability(io_capability_t::NO_INPUT_NO_OUTPUT), + _min_encryption_key_size(7), + _max_encryption_key_size(16), + _control_blocks(NULL), + resolving_list_entry_count(0) +{ + +} + +nRF5xSecurityManager::~nRF5xSecurityManager() +{ + terminate(); +} + +//////////////////////////////////////////////////////////////////////////// +// SM lifecycle management +// + +ble_error_t nRF5xSecurityManager::initialize() +{ +#if defined(MBEDTLS_ECDH_C) + if (_crypto.generate_keys( + make_ArrayView(X), + make_ArrayView(Y), + make_ArrayView(secret) + )) { + return BLE_ERROR_NONE; + } + + return BLE_ERROR_INTERNAL_STACK_FAILURE; +#endif + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::terminate() +{ + release_all_pairing_cb(); + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::reset() +{ + ble_error_t err = terminate(); + if (err) { + return err; + } + + return initialize(); +} + +//////////////////////////////////////////////////////////////////////////// +// Resolving list management +// + +// FIXME: on nordic, the irk is passed in sd_ble_gap_scan_start where whitelist +// and resolving list are all mixed up. + +uint8_t nRF5xSecurityManager::read_resolving_list_capacity() +{ + return MAX_RESOLVING_LIST_ENTRIES; +} + +ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk +) { + if (resolving_list_entry_count >= MAX_RESOLVING_LIST_ENTRIES) { + return BLE_ERROR_INVALID_STATE; + } + + resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count]; + entry.peer_identity_address_type = peer_identity_address_type; + entry.peer_identity_address = peer_identity_address; + entry.peer_irk = peer_irk; + + ++resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) { + size_t entry_index; + + // first the index needs to be found + for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) { + resolving_list_entry_t& entry = resolving_list[entry_index]; + if (entry.peer_identity_address_type == peer_identity_address_type && + entry.peer_identity_address == peer_identity_address + ) { + break; + } + } + + if (entry_index == resolving_list_entry_count) { + return BLE_ERROR_INVALID_PARAM; + } + + // Elements after the entry can be moved in the list + for (size_t i = entry_index; i < (resolving_list_entry_count - 1); ++i) { + resolving_list[i] = resolving_list[i + 1]; + } + + --resolving_list_entry_count; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::clear_resolving_list() +{ + resolving_list_entry_count = 0; + return BLE_ERROR_NONE; +} + +ArrayView +nRF5xSecurityManager::get_resolving_list() { + return ArrayView( + resolving_list, + resolving_list_entry_count + ); +} + +const nRF5xSecurityManager::resolving_list_entry_t* +nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { +#if defined(MBEDTLS_ECDH_C) + typedef byte_array_t hash_t; + + for (size_t i = 0; i < resolving_list_entry_count; ++i) { + resolving_list_entry_t& entry = resolving_list[i]; + hash_t hash_generated; + + // Compute the hash part from the random address part when the irk of + // the entry is used + _crypto.ah( + make_const_ArrayView(entry.peer_irk), + make_const_ArrayView( + resolvable_address.data() + CryptoToolbox::hash_size_ + ), + make_ArrayView(hash_generated) + ); + + // Compare hash generated with the hash present in the address passed as + // parameter. If they are equal then the IRK of the entry has been used + // to generate the resolvable address. + if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) { + return &entry; + } + } +#endif + return NULL; +} + + + +//////////////////////////////////////////////////////////////////////////// +// Pairing +// + + +ble_error_t nRF5xSecurityManager::send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + // allocate the control block required for the procedure completion + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_INITIATOR; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_NO_MEM; + } + pairing_cb->role = PAIRING_RESPONDER; + + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + + ble_gap_sec_params_t security_params = make_security_params( + oob_data_flag, + authentication_requirements, + initiator_dist, + responder_dist + ); + + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ &security_params, + /* keys */ &keyset + ); + + if (err) { + release_pairing_cb(pairing_cb); + } + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::cancel_pairing( + connection_handle_t connection, pairing_failure_t reason +) { + // this is the default path except when a key is expected to be entered by + // the user. + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + reason.value() | 0x80, + /* sec params */ NULL, + /* keyset */ NULL + ); + + if (!err) { + return BLE_ERROR_NONE; + } + + // Failed because we're in the wrong state; try to cancel pairing with + // sd_ble_gap_auth_key_reply + if (err == NRF_ERROR_INVALID_STATE) { + err = sd_ble_gap_auth_key_reply( + connection, + /* key type */ BLE_GAP_AUTH_KEY_TYPE_NONE, + /* key */ NULL + ); + } + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Feature support +// + +ble_error_t nRF5xSecurityManager::get_secure_connections_support( + bool &enabled +) { + enabled = true; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_io_capability(io_capability_t io_capability) +{ + _io_capability = io_capability; + return BLE_ERROR_NONE; +} + +//////////////////////////////////////////////////////////////////////////// +// Security settings +// + +ble_error_t nRF5xSecurityManager::set_authentication_timeout( + connection_handle_t connection, uint16_t timeout_in_10ms +) { + ble_opt_t opt; + opt.gap_opt.auth_payload_timeout.conn_handle = connection; + opt.gap_opt.auth_payload_timeout.auth_payload_timeout = timeout_in_10ms; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, &opt); + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::get_authentication_timeout( + connection_handle_t connection, uint16_t &timeout_in_10ms +) { + ble_opt_t opt; + opt.gap_opt.auth_payload_timeout.conn_handle = connection; + + uint32_t err = sd_ble_opt_get(BLE_GAP_OPT_AUTH_PAYLOAD_TIMEOUT, &opt); + if (err) { + return convert_sd_error(err); + } + + timeout_in_10ms = opt.gap_opt.auth_payload_timeout.auth_payload_timeout; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size +) { + if ((min_encryption_key_size < 7) || (min_encryption_key_size > 16) || + (min_encryption_key_size > max_encryption_key_size)) { + return BLE_ERROR_INVALID_PARAM; + } + + _min_encryption_key_size = min_encryption_key_size; + _max_encryption_key_size = max_encryption_key_size; + + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication +) { + // In the peripheral role, only the bond, mitm, lesc and keypress fields of + // this structure are used. + ble_gap_sec_params_t security_params = { + /* bond */ authentication.get_bondable(), + /* mitm */ authentication.get_mitm(), + /* lesc */ authentication.get_secure_connections(), + /* keypress */ authentication.get_keypress_notification(), + /* remainder of the data structure is ignored */ 0 + }; + + uint32_t err = sd_ble_gap_authenticate( + connection, + &security_params + ); + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Encryption +// + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm +) { + ble_gap_master_id_t master_id; + memcpy(master_id.rand, rand.data(), rand.size()); + memcpy(&master_id.ediv, ediv.data(), ediv.size()); + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = false; + enc_info.auth = mitm; + + // FIXME: how to pass the lenght of the LTK ??? + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm +) { + ble_gap_master_id_t master_id = {0}; + + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = true; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + uint32_t err = sd_ble_gap_encrypt( + connection, + &master_id, + &enc_info + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data +) { + nrf_ecb_hal_data_t ecb; + memcpy(&ecb.key, key.data(), key.size()); + memcpy(&ecb.cleartext, data.data(), data.size()); + + uint32_t err = sd_ecb_block_encrypt(&ecb); + if (err) { + return convert_sd_error(err); + } + + memcpy(data.data(), &ecb.ciphertext, data.size()); + return BLE_ERROR_NONE; +} + +//////////////////////////////////////////////////////////////////////////// +// Privacy +// + +ble_error_t nRF5xSecurityManager::set_private_address_timeout( + uint16_t timeout_in_seconds +) { + ble_gap_privacy_params_t privacy_config; + + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return convert_sd_error(err); + } + + privacy_config.private_addr_cycle_s = timeout_in_seconds; + err = sd_ble_gap_privacy_set(&privacy_config); + + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// Keys +// + +ble_error_t nRF5xSecurityManager::set_ltk( + connection_handle_t connection, + const ltk_t& ltk, + bool mitm, + bool secure_connections +) { + ble_gap_enc_info_t enc_info; + memcpy(enc_info.ltk, ltk.data(), ltk.size()); + enc_info.lesc = secure_connections; + enc_info.auth = mitm; + enc_info.ltk_len = ltk.size(); + + // FIXME: provide peer irk and csrk ? + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + &enc_info, + /* id info */ NULL, + /* sign info */ NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_ltk_not_found( + connection_handle_t connection +) { + uint32_t err = sd_ble_gap_sec_info_reply( + connection, + NULL, + NULL, + NULL // Not supported + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_irk(const irk_t& irk) +{ + + ble_gap_privacy_params_t privacy_config; + + // get the previous config + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return convert_sd_error(err); + } + + // set the new irk + memcpy(privacy_config.p_device_irk, irk.data(), irk.size()); + err = sd_ble_gap_privacy_set(&privacy_config); + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::set_csrk( + const csrk_t& csrk, + sign_count_t sign_counter +) { + _csrk = csrk; + _sign_counter = sign_counter; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xSecurityManager::set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter +) { + return BLE_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////////// +// Authentication +// + +ble_error_t nRF5xSecurityManager::get_random_data(byte_array_t<8> &random_data) +{ + uint32_t err = sd_rand_application_vector_get( + random_data.data(), random_data.size() + ); + return convert_sd_error(err); +} + +//////////////////////////////////////////////////////////////////////////// +// MITM +// + +ble_error_t nRF5xSecurityManager::set_display_passkey(passkey_num_t passkey) +{ + PasskeyAscii passkey_ascii(passkey); + ble_opt_t sd_passkey; + sd_passkey.gap_opt.passkey.p_passkey = passkey ? passkey_ascii.value() : NULL; + uint32_t err = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sd_passkey); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::passkey_request_reply( + connection_handle_t connection, const passkey_num_t passkey +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + PasskeyAscii pkasc(passkey); + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, + pkasc.value() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + ble_gap_lesc_oob_data_t oob_own; + ble_gap_lesc_oob_data_t oob_peer; + + // is own address important ? + memcpy(oob_own.r, local_random.data(), local_random.size()); + // FIXME: What to do with local confirm ??? + + // is peer address important ? + memcpy(oob_peer.r, peer_random.data(), peer_random.size()); + memcpy(oob_peer.c, peer_confirm.data(), peer_confirm.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_set( + connection, + pairing_cb->own_oob ? &oob_own : NULL, + pairing_cb->peer_oob ? &oob_peer : NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t& oob_data +) { + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + BLE_GAP_AUTH_KEY_TYPE_OOB, + oob_data.data() + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::confirmation_entered( + connection_handle_t connection, bool confirmation +) { + pairing_control_block_t* pairing_cb = get_pairing_cb(connection); + if (!pairing_cb) { + return BLE_ERROR_INVALID_STATE; + } + + uint32_t err = sd_ble_gap_auth_key_reply( + connection, + confirmation ? BLE_GAP_AUTH_KEY_TYPE_PASSKEY : BLE_GAP_AUTH_KEY_TYPE_NONE, + NULL + ); + + return convert_sd_error(err); +} + +ble_error_t nRF5xSecurityManager::send_keypress_notification( + connection_handle_t connection, Keypress_t keypress +) { + uint32_t err = sd_ble_gap_keypress_notify( + connection, + static_cast(keypress) + ); + return convert_sd_error(err); +} + + +ble_error_t nRF5xSecurityManager::generate_secure_connections_oob() +{ +#if defined(MBEDTLS_ECDH_C) + ble_gap_lesc_p256_pk_t own_secret; + ble_gap_lesc_oob_data_t oob_data; + + memcpy(own_secret.pk, secret.data(), secret.size()); + + uint32_t err = sd_ble_gap_lesc_oob_data_get( + BLE_CONN_HANDLE_INVALID, + &own_secret, + &oob_data + ); + + if (!err) { + get_event_handler()->on_secure_connections_oob_generated( + oob_data.r, + oob_data.c + ); + } + + return convert_sd_error(err); +#endif + return BLE_ERROR_NOT_IMPLEMENTED; +} + +nRF5xSecurityManager& nRF5xSecurityManager::get_security_manager() +{ + static nRF5xSecurityManager _security_manager; + return _security_manager; +} + +bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) +{ + nRF5xSecurityManager& self = nRF5xSecurityManager::get_security_manager(); + SecurityManager::EventHandler* handler = self.get_event_handler(); + + if ((evt == NULL) || (handler == NULL)) { + return false; + } + + const ble_gap_evt_t& gap_evt = evt->evt.gap_evt; + uint16_t connection = gap_evt.conn_handle; + pairing_control_block_t* pairing_cb = self.get_pairing_cb(connection); + + switch (evt->header.evt_id) { + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { + const ble_gap_sec_params_t& params = + gap_evt.params.sec_params_request.peer_params; + + KeyDistribution initiator_dist( + params.kdist_peer.enc, + params.kdist_peer.id, + params.kdist_peer.sign, + params.kdist_peer.link + ); + + KeyDistribution responder_dist( + params.kdist_own.enc, + params.kdist_own.id, + params.kdist_own.sign, + params.kdist_own.link + ); + + if (pairing_cb && pairing_cb->role == PAIRING_INITIATOR) { + // when this event is received by an initiator, it should not be + // forwarded via the handler; this is not a behaviour expected + // by the bluetooth standard ... + ble_gap_sec_keyset_t keyset = make_keyset( + *pairing_cb, + initiator_dist, + responder_dist + ); + uint32_t err = sd_ble_gap_sec_params_reply( + connection, + /* status */ BLE_GAP_SEC_STATUS_SUCCESS, + /* params */ NULL, + /* keys ... */ &keyset + ); + + // in case of error; release the pairing control block and signal + // it to the event handler + if (err) { + release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + pairing_failure_t::UNSPECIFIED_REASON + ); + } + } else { + handler->on_pairing_request( + connection, + params.oob, + AuthenticationMask( + params.bond, + params.mitm, + params.lesc, + params.keypress + ), + initiator_dist, + responder_dist + ); + } + return true; + } + + case BLE_GAP_EVT_SEC_INFO_REQUEST: { + const ble_gap_evt_sec_info_request_t& req = + gap_evt.params.sec_info_request; + + handler->on_ltk_request( + connection, + ediv_t((uint8_t*)(&req.master_id.ediv)), + rand_t(req.master_id.rand) + ); + + return true; + } + + case BLE_GAP_EVT_PASSKEY_DISPLAY: { + const ble_gap_evt_passkey_display_t& req = + gap_evt.params.passkey_display; + + if (req.match_request == 0) { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + } else { + handler->on_passkey_display( + connection, + PasskeyAscii::to_num(req.passkey) + ); + handler->on_confirmation_request(connection); + } + + return true; + } + + case BLE_GAP_EVT_KEY_PRESSED: { + handler->on_keypress_notification( + connection, + (Keypress_t)gap_evt.params.key_pressed.kp_not + ); + return true; + } + + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { + uint8_t key_type = gap_evt.params.auth_key_request.key_type; + + switch (key_type) { + case BLE_GAP_AUTH_KEY_TYPE_NONE: // Illegal + break; + + case BLE_GAP_AUTH_KEY_TYPE_PASSKEY: + handler->on_passkey_request(connection); + break; + + case BLE_GAP_AUTH_KEY_TYPE_OOB: + handler->on_legacy_pairing_oob_request(connection); + break; + } + + return true; + } + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: { +#if defined(MBEDTLS_ECDH_C) + const ble_gap_evt_lesc_dhkey_request_t& dhkey_request = + gap_evt.params.lesc_dhkey_request; + + static const size_t key_size = public_key_coord_t::size_; + ble_gap_lesc_dhkey_t shared_secret; + + _crypto.generate_shared_secret( + make_const_ArrayView(dhkey_request.p_pk_peer->pk), + make_const_ArrayView(dhkey_request.p_pk_peer->pk + key_size), + make_const_ArrayView(secret), + shared_secret.key + ); + + sd_ble_gap_lesc_dhkey_reply(connection, &shared_secret); + + if (dhkey_request.oobd_req) { + handler->on_secure_connections_oob_request(connection); + } +#endif + return true; + } + + case BLE_GAP_EVT_AUTH_STATUS: { + const ble_gap_evt_auth_status_t& status = gap_evt.params.auth_status; + + switch (status.auth_status) { + // NOTE: pairing_cb must be valid if this event has been + // received as it is being allocated earlier and release + // in this block + // The memory is released before the last call to the event handler + // to free the heap a bit before subsequent allocation with user + // code. + case BLE_GAP_SEC_STATUS_SUCCESS: { + KeyDistribution own_dist; + KeyDistribution peer_dist; + + if (pairing_cb->role == PAIRING_INITIATOR) { + own_dist = pairing_cb->initiator_dist; + peer_dist = pairing_cb->responder_dist; + } else { + own_dist = pairing_cb->responder_dist; + peer_dist = pairing_cb->initiator_dist; + } + + if (own_dist.get_encryption()) { + handler->on_keys_distributed_local_ltk( + connection, + ltk_t(pairing_cb->own_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_local_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->own_enc_key.master_id.ediv + )), + pairing_cb->own_enc_key.master_id.rand + ); + } + + if (peer_dist.get_encryption()) { + handler->on_keys_distributed_ltk( + connection, + ltk_t(pairing_cb->peer_enc_key.enc_info.ltk) + ); + + handler->on_keys_distributed_ediv_rand( + connection, + ediv_t(reinterpret_cast( + &pairing_cb->peer_enc_key.master_id.ediv + )), + pairing_cb->peer_enc_key.master_id.rand + ); + } + + if (peer_dist.get_identity()) { + handler->on_keys_distributed_irk( + connection, + irk_t(pairing_cb->peer_id_key.id_info.irk) + ); + + advertising_peer_address_type_t + address_type(advertising_peer_address_type_t::PUBLIC_ADDRESS); + + if (pairing_cb->peer_id_key.id_addr_info.addr_type) { + address_type = advertising_peer_address_type_t::RANDOM_ADDRESS; + } + + handler->on_keys_distributed_bdaddr( + connection, + address_type, + ble::address_t(pairing_cb->peer_id_key.id_addr_info.addr) + ); + } + + if (peer_dist.get_signing()) { + handler->on_keys_distributed_csrk( + connection, + pairing_cb->peer_sign_key.csrk + ); + } + + self.release_pairing_cb(pairing_cb); + handler->on_pairing_completed(connection); + break; + } + + case BLE_GAP_SEC_STATUS_TIMEOUT: + if (!pairing_cb) { + // Note: if pairing_cb does not exist then the timeout; + // is caused by a security request as the paiting_cb is + // created when the module receive the pairing request. + handler->on_link_encryption_request_timed_out(connection); + } else { + self.release_pairing_cb(pairing_cb); + handler->on_pairing_timed_out(connection); + } + break; + + case BLE_GAP_SEC_STATUS_PASSKEY_ENTRY_FAILED: + case BLE_GAP_SEC_STATUS_OOB_NOT_AVAILABLE: + case BLE_GAP_SEC_STATUS_AUTH_REQ: + case BLE_GAP_SEC_STATUS_CONFIRM_VALUE: + case BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP: + case BLE_GAP_SEC_STATUS_ENC_KEY_SIZE: + case BLE_GAP_SEC_STATUS_SMP_CMD_UNSUPPORTED: + case BLE_GAP_SEC_STATUS_UNSPECIFIED: + case BLE_GAP_SEC_STATUS_REPEATED_ATTEMPTS: + case BLE_GAP_SEC_STATUS_INVALID_PARAMS: + case BLE_GAP_SEC_STATUS_DHKEY_FAILURE: + case BLE_GAP_SEC_STATUS_NUM_COMP_FAILURE: + case BLE_GAP_SEC_STATUS_BR_EDR_IN_PROG: + case BLE_GAP_SEC_STATUS_X_TRANS_KEY_DISALLOWED: + self.release_pairing_cb(pairing_cb); + handler->on_pairing_error( + connection, + (pairing_failure_t::type) (status.auth_status & 0xF) + ); + break; + + default: + self.release_pairing_cb(pairing_cb); + break; + } + + return true; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { + const ble_gap_evt_conn_sec_update_t& req = + gap_evt.params.conn_sec_update; + + if((req.conn_sec.sec_mode.sm == 1) && (req.conn_sec.sec_mode.lv >= 2)) { + handler->on_link_encryption_result( + connection, link_encryption_t::ENCRYPTED + ); + } else { + handler->on_link_encryption_result( + connection, link_encryption_t::NOT_ENCRYPTED + ); + } + return true; + } + + case BLE_GAP_EVT_TIMEOUT: { + switch (gap_evt.params.timeout.src) { + case BLE_GAP_TIMEOUT_SRC_AUTH_PAYLOAD: + handler->on_valid_mic_timeout(connection); + return true; + + default: + return false; + } + return false; + } + + case BLE_GAP_EVT_SEC_REQUEST: { + const ble_gap_evt_sec_request_t& req = gap_evt.params.sec_request; + handler->on_slave_security_request( + connection, + AuthenticationMask(req.bond, req.mitm, req.lesc, req.keypress) + ); + return true; + } + + default: + return false; + } +} + +ble_gap_sec_params_t nRF5xSecurityManager::make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + ble_gap_sec_params_t security_params = { + /* bond */ authentication_requirements.get_bondable(), + /* mitm */ authentication_requirements.get_mitm(), + /* lesc */ authentication_requirements.get_secure_connections(), + /* keypress */ authentication_requirements.get_keypress_notification(), + /* io_caps */ _io_capability.value(), + /* oob */ oob_data_flag, + /* min_key_size */ _min_encryption_key_size, + /* max_key_size */ _max_encryption_key_size, + /* kdist_periph */ { + /* enc */ responder_dist.get_encryption(), + /* id */ responder_dist.get_identity(), + /* sign */ responder_dist.get_signing(), + /* link */ responder_dist.get_link() + }, + /* kdist_central */ { + /* enc */ initiator_dist.get_encryption(), + /* id */ initiator_dist.get_identity(), + /* sign */ initiator_dist.get_signing(), + /* link */ initiator_dist.get_link() + } + }; + return security_params; +} + +ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist +) { + pairing_cb.initiator_dist = initiator_dist; + pairing_cb.responder_dist = responder_dist; + + KeyDistribution* own_dist = NULL; + KeyDistribution* peer_dist = NULL; + + if (pairing_cb.role == PAIRING_INITIATOR) { + own_dist = &initiator_dist; + peer_dist = &responder_dist; + } else { + own_dist = &responder_dist; + peer_dist = &initiator_dist; + } + + ble_gap_sec_keyset_t keyset = { + /* keys_own */ { + own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL, + own_dist->get_identity() ? &pairing_cb.own_id_key : NULL, + own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL, + &pairing_cb.own_pk + }, + /* keys_peer */ { + peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL, + peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL, + peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL, + &pairing_cb.peer_pk + } + }; + + // copy csrk if necessary + if (keyset.keys_own.p_sign_key) { + memcpy(keyset.keys_own.p_sign_key->csrk, _csrk.data(), _csrk.size()); + } + + // copy public keys used +#if defined(MBEDTLS_ECDH_C) + memcpy(pairing_cb.own_pk.pk, X.data(), X.size()); + memcpy(pairing_cb.own_pk.pk + X.size(), Y.data(), Y.size()); +#endif + return keyset; +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::allocate_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pairing_cb = + new (std::nothrow) pairing_control_block_t(); + if (pairing_cb) { + pairing_cb->next = _control_blocks; + _control_blocks = pairing_cb; + } + return pairing_cb; +} + +void nRF5xSecurityManager::release_pairing_cb(pairing_control_block_t* pairing_cb) +{ + if (pairing_cb == _control_blocks) { + _control_blocks = _control_blocks->next; + delete pairing_cb; + } else { + pairing_control_block_t* it = _control_blocks; + while (it->next) { + if (it->next == pairing_cb) { + it->next = pairing_cb->next; + delete pairing_cb; + return; + } + it = it->next; + } + } +} + +nRF5xSecurityManager::pairing_control_block_t* +nRF5xSecurityManager::get_pairing_cb(connection_handle_t connection) +{ + pairing_control_block_t* pcb = _control_blocks; + while (pcb) { + if (pcb->connection == connection) { + return pcb; + } + pcb = pcb->next; + } + + return NULL; +} + +void nRF5xSecurityManager::release_all_pairing_cb() +{ + while(_control_blocks) { + release_pairing_cb(_control_blocks); + } +} + +} // nordic +} // vendor +} // pal +} // ble + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h new file mode 100644 index 0000000000..e88e9075f9 --- /dev/null +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h @@ -0,0 +1,403 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018-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 NRF5X_PAL_SECURITY_MANAGER_ +#define NRF5X_PAL_SECURITY_MANAGER_ + +#include "ble/BLETypes.h" +#include "ble/pal/PalSecurityManager.h" +#include "nrf_ble.h" +#include "nRF5xCrypto.h" + + +namespace ble { +namespace pal { +namespace vendor { +namespace nordic { + +class nRF5xSecurityManager : public ::ble::pal::SecurityManager { +public: + nRF5xSecurityManager(); + + virtual ~nRF5xSecurityManager(); + + //////////////////////////////////////////////////////////////////////////// + // SM lifecycle management + // + + /** + * @see ::ble::pal::SecurityManager::initialize + */ + virtual ble_error_t initialize(); + + /** + * @see ::ble::pal::SecurityManager::terminate + */ + virtual ble_error_t terminate(); + + /** + * @see ::ble::pal::SecurityManager::reset + */ + virtual ble_error_t reset() ; + + //////////////////////////////////////////////////////////////////////////// + // Resolving list management + // + + /** + * @see ::ble::pal::SecurityManager::read_resolving_list_capacity + */ + virtual uint8_t read_resolving_list_capacity(); + + /** + * @see ::ble::pal::SecurityManager::add_device_to_resolving_list + */ + virtual ble_error_t add_device_to_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address, + const irk_t &peer_irk + ); + + /** + * @see ::ble::pal::SecurityManager::remove_device_from_resolving_list + */ + virtual ble_error_t remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address + ); + + /** + * @see ::ble::pal::SecurityManager::clear_resolving_list + */ + virtual ble_error_t clear_resolving_list(); + + /** + * An entry of the resolving list stored in the SecurityManager. + */ + struct resolving_list_entry_t { + resolving_list_entry_t() : + peer_identity_address_type( + advertising_peer_address_type_t::PUBLIC_ADDRESS + ) + { } + + irk_t peer_irk; + address_t peer_identity_address; + advertising_peer_address_type_t peer_identity_address_type; + }; + + /** + * Return the IRKs present in the resolving list + * @param count The number of entries present in the resolving list. + * @param pointer to the first entry of the resolving list. + */ + ArrayView get_resolving_list(); + + /** + * Try to resolve a private resolvable address. + * + * @param resolvable_address The address to resolve. + * + * @return Pointer to the entry found if any. + */ + const resolving_list_entry_t* resolve_address( + const address_t& resolvable_address + ); + + + //////////////////////////////////////////////////////////////////////////// + // Pairing + // + + /** + * @see ::ble::pal::SecurityManager::send_pairing_request + */ + virtual ble_error_t send_pairing_request( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::send_pairing_response + */ + virtual ble_error_t send_pairing_response( + connection_handle_t connection, + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + /** + * @see ::ble::pal::SecurityManager::cancel_pairing + */ + virtual ble_error_t cancel_pairing( + connection_handle_t connection, pairing_failure_t reason + ); + + + //////////////////////////////////////////////////////////////////////////// + // Feature support + // + + /** + * @see ::ble::pal::SecurityManager::get_secure_connections_support + */ + virtual ble_error_t get_secure_connections_support( + bool &enabled + ); + + /** + * @see ::ble::pal::SecurityManager::set_io_capability + */ + virtual ble_error_t set_io_capability(io_capability_t io_capability); + + //////////////////////////////////////////////////////////////////////////// + // Security settings + // + + /** + * @see ::ble::pal::SecurityManager::set_authentication_timeout + */ + virtual ble_error_t set_authentication_timeout( + connection_handle_t, uint16_t timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::get_authentication_timeout + */ + virtual ble_error_t get_authentication_timeout( + connection_handle_t, uint16_t &timeout_in_10ms + ); + + /** + * @see ::ble::pal::SecurityManager::set_encryption_key_requirements + */ + virtual ble_error_t set_encryption_key_requirements( + uint8_t min_encryption_key_size, + uint8_t max_encryption_key_size + ); + + /** + * @see ::ble::pal::SecurityManager::slave_security_request + */ + virtual ble_error_t slave_security_request( + connection_handle_t connection, + AuthenticationMask authentication + ); + + //////////////////////////////////////////////////////////////////////////// + // Encryption + // + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + const rand_t &rand, + const ediv_t &ediv, + bool mitm + ); + + /** + * @see ::ble::pal::SecurityManager::enable_encryption + */ + virtual ble_error_t enable_encryption( + connection_handle_t connection, + const ltk_t <k, + bool mitm + ) ; + + /** + * @see ::ble::pal::SecurityManager::encrypt_data + */ + virtual ble_error_t encrypt_data( + const byte_array_t<16> &key, + encryption_block_t &data + ); + + //////////////////////////////////////////////////////////////////////////// + // Privacy + // + + /** + * @see ::ble::pal::SecurityManager::set_private_address_timeout + */ + virtual ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds); + + //////////////////////////////////////////////////////////////////////////// + // Keys + // + + /** + * @see ::ble::pal::SecurityManager::set_ltk + */ + virtual ble_error_t set_ltk( + connection_handle_t connection, + const ltk_t <k, + bool mitm, + bool secure_connections + ); + + /** + * @see ::ble::pal::SecurityManager::set_ltk_not_found + */ + virtual ble_error_t set_ltk_not_found( + connection_handle_t connection + ); + + /** + * @see ::ble::pal::SecurityManager::set_irk + */ + virtual ble_error_t set_irk(const irk_t &irk); + + /** + * @see ::ble::pal::SecurityManager::set_csrk + */ + virtual ble_error_t set_csrk(const csrk_t &csrk, sign_count_t sign_counter); + + /** + * @see ::ble::pal::SecurityManager::set_peer_csrk + */ + virtual ble_error_t set_peer_csrk( + connection_handle_t connection, + const csrk_t &csrk, + bool authenticated, + sign_count_t sign_counter + ); + + + //////////////////////////////////////////////////////////////////////////// + // Authentication + // + + /** + * @see ::ble::pal::SecurityManager::get_random_data + */ + virtual ble_error_t get_random_data(byte_array_t<8> &random_data); + + //////////////////////////////////////////////////////////////////////////// + // MITM + // + + /** + * @see ::ble::pal::SecurityManager::set_display_passkey + */ + virtual ble_error_t set_display_passkey(passkey_num_t passkey); + + /** + * @see ::ble::pal::SecurityManager::passkey_request_reply + */ + virtual ble_error_t passkey_request_reply( + connection_handle_t connection, + passkey_num_t passkey + ); + + /** + * @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply + */ + virtual ble_error_t secure_connections_oob_request_reply( + connection_handle_t connection, + const oob_lesc_value_t &local_random, + const oob_lesc_value_t &peer_random, + const oob_confirm_t &peer_confirm + ); + + /** + * @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply + */ + virtual ble_error_t legacy_pairing_oob_request_reply( + connection_handle_t connection, + const oob_tk_t &oob_data + ); + + /** + * @see ::ble::pal::SecurityManager::confirmation_entered + */ + virtual ble_error_t confirmation_entered( + connection_handle_t connection, bool confirmation + ); + + /** + * @see ::ble::pal::SecurityManager::send_keypress_notification + */ + virtual ble_error_t send_keypress_notification( + connection_handle_t connection, Keypress_t keypress + ); + + /** + * @see ::ble::pal::SecurityManager::generate_secure_connections_oob + */ + virtual ble_error_t generate_secure_connections_oob(); + + // singleton of nordic Security Manager + static nRF5xSecurityManager& get_security_manager(); + + // Event handler + bool sm_handler(const ble_evt_t *evt); + +private: + csrk_t _csrk; + sign_count_t _sign_counter; + io_capability_t _io_capability; + uint8_t _min_encryption_key_size; + uint8_t _max_encryption_key_size; + + struct pairing_control_block_t; + + ble_gap_sec_params_t make_security_params( + bool oob_data_flag, + AuthenticationMask authentication_requirements, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + ble_gap_sec_keyset_t make_keyset( + pairing_control_block_t& pairing_cb, + KeyDistribution initiator_dist, + KeyDistribution responder_dist + ); + + pairing_control_block_t* allocate_pairing_cb(connection_handle_t connection); + void release_pairing_cb(pairing_control_block_t* pairing_cb); + pairing_control_block_t* get_pairing_cb(connection_handle_t connection); + void release_all_pairing_cb(); + + pairing_control_block_t* _control_blocks; +#if defined(MBEDTLS_ECDH_C) + CryptoToolbox _crypto; + ble::public_key_coord_t X; + ble::public_key_coord_t Y; + ble::public_key_coord_t secret; +#endif + + static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; + + size_t resolving_list_entry_count; + resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; +}; + +} // nordic +} // vendor +} // pal +} // ble + +#endif /* NRF5X_PAL_SECURITY_MANAGER_ */ From ed20b17d296ac4238bd768686a21271cd513c4ad Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:09:38 +0100 Subject: [PATCH 208/274] Nordic BLE: Fix link count --- .../TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json | 4 ++-- .../TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json index 55ecb9abc4..f0c7b9261d 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S132/mbed_lib.json @@ -14,8 +14,8 @@ "NRF_SDH_ENABLED=1", "NRF_SDH_BLE_ENABLED=1", "PEER_MANAGER_ENABLED=1", - "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", - "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=1", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=3", "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", "NRF_SDH_BLE_SERVICE_CHANGED=1", "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23", diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json index f72a514443..4896fa62fd 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_S140/mbed_lib.json @@ -12,8 +12,8 @@ "NRF_SDH_ENABLED=1", "NRF_SDH_BLE_ENABLED=1", "PEER_MANAGER_ENABLED=1", - "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=3", - "NRF_SDH_BLE_CENTRAL_LINK_COUNT=1", + "NRF_SDH_BLE_PERIPHERAL_LINK_COUNT=1", + "NRF_SDH_BLE_CENTRAL_LINK_COUNT=3", "NRF_SDH_BLE_TOTAL_LINK_COUNT=4", "NRF_SDH_BLE_SERVICE_CHANGED=1", "NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23", From f5ac8d69ce752e2d8896ea9a7cc2c62fec7d2e91 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:10:05 +0100 Subject: [PATCH 209/274] Nordic: Adjust RAM requirements. --- .../TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct | 4 ++-- .../TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld | 4 ++-- .../TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf | 4 ++-- .../TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct | 4 ++-- .../TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld | 4 ++-- .../TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct index e69ed0c74f..2bdba912a1 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_ARM_STD/nRF52832.sct @@ -14,8 +14,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x10000 #else - #define MBED_RAM_START 0x20003800 - #define MBED_RAM_SIZE 0xC800 + #define MBED_RAM_START 0x200031D0 + #define MBED_RAM_SIZE 0xCE30 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld index fd78080909..0fa07980fc 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_GCC_ARM/NRF52832.ld @@ -30,8 +30,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x10000 #else - #define MBED_RAM_START 0x20003800 - #define MBED_RAM_SIZE 0xC800 + #define MBED_RAM_START 0x200031D0 + #define MBED_RAM_SIZE 0xCE30 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf index d66a6ab5ab..fd96dc6952 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52832/device/TOOLCHAIN_IAR/nRF52832.icf @@ -16,8 +16,8 @@ if (MBED_APP_START == 0) { define symbol MBED_RAM_START = 0x20000000; define symbol MBED_RAM_SIZE = 0x10000; } else { - define symbol MBED_RAM_START = 0x20003800; - define symbol MBED_RAM_SIZE = 0xC800; + define symbol MBED_RAM_START = 0x20003188; + define symbol MBED_RAM_SIZE = 0x3CE78; } define symbol MBED_RAM0_START = MBED_RAM_START; diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct index 6849dc2239..8aaa8a42ba 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_ARM_STD/nRF52840.sct @@ -14,8 +14,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x40000 #else - #define MBED_RAM_START 0x20003700 - #define MBED_RAM_SIZE 0x3C900 + #define MBED_RAM_START 0x20003188 + #define MBED_RAM_SIZE 0x3CE78 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld index 55f39e9c4f..99b8a4e4dd 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_GCC_ARM/NRF52840.ld @@ -30,8 +30,8 @@ #define MBED_RAM_START 0x20000000 #define MBED_RAM_SIZE 0x40000 #else - #define MBED_RAM_START 0x20003700 - #define MBED_RAM_SIZE 0x3C900 + #define MBED_RAM_START 0x20003188 + #define MBED_RAM_SIZE 0x3CE78 #endif #define MBED_RAM0_START MBED_RAM_START diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf index 2605356911..95819fe1df 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_NRF52/TARGET_MCU_NRF52840/device/TOOLCHAIN_IAR/nRF52840.icf @@ -16,8 +16,8 @@ if (MBED_APP_START == 0) { define symbol MBED_RAM_START = 0x20000000; define symbol MBED_RAM_SIZE = 0x40000; } else { - define symbol MBED_RAM_START = 0x20003700; - define symbol MBED_RAM_SIZE = 0x3C900; + define symbol MBED_RAM_START = 0x20003188; + define symbol MBED_RAM_SIZE = 0x3CE78; } define symbol MBED_RAM0_START = MBED_RAM_START; From 02e3c13d25bb8859a85e816a519e878ddedd2343 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:11:05 +0100 Subject: [PATCH 210/274] Nordic BLE: Protect event signaled flag. --- .../targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xn.cpp | 4 ++++ 1 file changed, 4 insertions(+) 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..e79e962ba0 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 @@ -233,8 +233,12 @@ nRF5xn::waitForEvent(void) } void nRF5xn::processEvents() { + core_util_critical_section_enter(); if (isEventsSignaled) { isEventsSignaled = false; + core_util_critical_section_exit(); intern_softdevice_events_execute(); + } else { + core_util_critical_section_exit(); } } From dc54da0a2d19b5a93cb972a62f55ed5c1f9ee61d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:12:55 +0100 Subject: [PATCH 211/274] Nordic BLE: Force signing and link requirements to false. --- .../TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp index 0be03868c6..b08c707012 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp @@ -797,6 +797,14 @@ bool nRF5xSecurityManager::sm_handler(const ble_evt_t *evt) ); if (pairing_cb && pairing_cb->role == PAIRING_INITIATOR) { + // override signing parameter + initiator_dist.set_signing(false); + responder_dist.set_signing(false); + + // override link parameter + initiator_dist.set_link(false); + responder_dist.set_link(false); + // when this event is received by an initiator, it should not be // forwarded via the handler; this is not a behaviour expected // by the bluetooth standard ... From 2af5508c4cb2cf9ab2d56f9e51d8edb1d06ce0be Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:15:53 +0100 Subject: [PATCH 212/274] Nordic BLE: Do not conditionnaly assign sm key pointers. This change has been forced by a change in latest softdevice that requires all key pointers to not be NULL unlike what is indicated in the documentation. --- .../source/nRF5xPalSecurityManager.cpp | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp index b08c707012..9b608c768e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp @@ -1136,28 +1136,17 @@ ble_gap_sec_keyset_t nRF5xSecurityManager::make_keyset( pairing_cb.initiator_dist = initiator_dist; pairing_cb.responder_dist = responder_dist; - KeyDistribution* own_dist = NULL; - KeyDistribution* peer_dist = NULL; - - if (pairing_cb.role == PAIRING_INITIATOR) { - own_dist = &initiator_dist; - peer_dist = &responder_dist; - } else { - own_dist = &responder_dist; - peer_dist = &initiator_dist; - } - ble_gap_sec_keyset_t keyset = { /* keys_own */ { - own_dist->get_encryption() ? &pairing_cb.own_enc_key : NULL, - own_dist->get_identity() ? &pairing_cb.own_id_key : NULL, - own_dist->get_signing() ? &pairing_cb.own_sign_key : NULL, + &pairing_cb.own_enc_key, + &pairing_cb.own_id_key, + &pairing_cb.own_sign_key, &pairing_cb.own_pk }, /* keys_peer */ { - peer_dist->get_encryption() ? &pairing_cb.peer_enc_key : NULL, - peer_dist->get_identity() ? &pairing_cb.peer_id_key : NULL, - peer_dist->get_signing() ? &pairing_cb.peer_sign_key : NULL, + &pairing_cb.peer_enc_key, + &pairing_cb.peer_id_key, + &pairing_cb.peer_sign_key, &pairing_cb.peer_pk } }; From 4a7c9a9a55b4b18358ad5a0133f305c157de77f7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:17:00 +0100 Subject: [PATCH 213/274] Nordic BLE: expose publically btle_handler --- .../TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index e1bbfa0327..62b5233233 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -76,9 +76,9 @@ void app_error_handler(uint32_t error_code, uint32_t line_num, const extern "C" void SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector. #if NRF_SDK14PLUS_EVENT_HANDLERS -static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); +void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); #else -static void btle_handler(ble_evt_t *p_ble_evt); +void btle_handler(ble_evt_t *p_ble_evt); #endif #if !NRF_SDK14PLUS_EVENT_HANDLERS @@ -263,9 +263,9 @@ error_t btle_init(void) } #if NRF_SDK14PLUS_EVENT_HANDLERS -static void btle_handler(const ble_evt_t *p_ble_evt, void *p_context) +void btle_handler(const ble_evt_t *p_ble_evt, void *p_context) #else -static void btle_handler(ble_evt_t *p_ble_evt) +void btle_handler(const ble_evt_t *p_ble_evt) #endif { #if NRF_SDK14PLUS_EVENT_HANDLERS From 68b3288ba81110b098583dcb72b4249aa70c4063 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:18:36 +0100 Subject: [PATCH 214/274] Nordic BLE: Fix signature of nRF5xGattServer::hwCallback --- .../TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp index 05ca55a57b..4963145059 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5xGattServer.cpp @@ -469,7 +469,7 @@ ble_error_t nRF5xGattServer::reset(void) @brief Callback handler for events getting pushed up from the SD */ /**************************************************************************/ -void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) +void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) { GattAttribute::Handle_t handle_value; GattServerEvents::gattEvent_t eventType; From 8fbecf2e0df3afdb3f70ded7b943661a3bf65149 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:20:12 +0100 Subject: [PATCH 215/274] Nordic BLE: Fix incorrect assignement --- .../targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp index e9448d68ed..adcb1f9f4d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp @@ -126,7 +126,7 @@ ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContex return BLE_ERROR_ALREADY_INITIALIZED; } - instanceID = instanceID; + this->instanceID = instanceID; /* ToDo: Clear memory contents, reset the SD, etc. */ if (btle_init() != ERROR_NONE) { From 6810c0260620bbd28a67404ac0d20c841d1d77f7 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 09:23:11 +0100 Subject: [PATCH 216/274] Nordic BLE: Fix processing of events. If new events are signaled during processing then they should be processed when processEvent is called again. The goal is to let other processing happen and not process sollely ble events. --- .../TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp index adcb1f9f4d..d2df994da1 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp @@ -223,19 +223,18 @@ nRF5xn::waitForEvent(void) void nRF5xn::processEvents() { core_util_critical_section_enter(); - while (isEventsSignaled) { + if (isEventsSignaled) { isEventsSignaled = false; core_util_critical_section_exit(); - #if NRF_SD_BLE_API_VERSION >= 5 +#if NRF_SD_BLE_API_VERSION >= 5 // We use the "polling" dispatch model // http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v14.2.0/group__nrf__sdh.html?cp=4_0_0_6_11_60_20#gab4d7be69304d4f5feefd1d440cc3e6c7 // This will process any pending events from the Softdevice nrf_sdh_evts_poll(); - #else +#else intern_softdevice_events_execute(); - #endif - - core_util_critical_section_enter(); +#endif + } else { + core_util_critical_section_exit(); } - core_util_critical_section_exit(); } From 39396955a2d99a2cf6f295b19e3ad480aafac16f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 10:52:23 +0100 Subject: [PATCH 217/274] Nordic BLE: simplify whitelist management. --- .../TARGET_NRF5x/source/nRF5xGap.cpp | 289 ++---------------- .../TARGET_NRF5x/source/nRF5xGap.h | 33 -- 2 files changed, 21 insertions(+), 301 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp index 09f99fb12f..5f701aa133 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp @@ -824,17 +824,33 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) } whitelistAddressesSize = whitelistIn.size; + ble_gap_addr_t* pp_addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; for (uint32_t i = 0; i < whitelistIn.size; ++i) { - memcpy(&whitelistAddresses[i].addr , &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr)); + memcpy(&whitelistAddresses[i].addr, &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr)); whitelistAddresses[i].addr_type = static_cast (whitelistIn.addresses[i].type); + pp_addrs[i] = &whitelistAddresses[i]; } -#if (NRF_SD_BLE_API_VERSION >= 3) - updateWhiteAndIdentityListInStack(); -#endif + ble_gap_addr_t** addresses_list_ptr = (whitelistIn.size == 0) ? NULL : pp_addrs; - return BLE_ERROR_NONE; + uint32_t err = sd_ble_gap_whitelist_set(addresses_list_ptr, whitelistAddressesSize); + + switch(err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + + case BLE_ERROR_GAP_WHITELIST_IN_USE: + return BLE_ERROR_INVALID_STATE; + + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + case NRF_ERROR_DATA_SIZE: + return BLE_ERROR_INVALID_PARAM; + + default: + return BLE_ERROR_UNSPECIFIED; + } } /**************************************************************************/ @@ -860,7 +876,6 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode) { advertisingPolicyMode = mode; - return BLE_ERROR_NONE; } @@ -973,267 +988,5 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } -#if (NRF_SD_BLE_API_VERSION <= 2) -/**************************************************************************/ -/*! - @brief Helper function used to populate the ble_gap_whitelist_t that - will be used by the SoftDevice for filtering requests. - @returns \ref ble_error_t - @retval BLE_ERROR_NONE - Everything executed properly - - @retval BLE_ERROR_INVALID_STATE - The internal stack was not initialized correctly. - - @note Both the SecurityManager and Gap must initialize correctly for - this function to succeed. - - @note This function is needed because for the BLE API the whitelist - is just a collection of keys, but for the stack it also includes - the IRK table. - - @section EXAMPLE - - @code - - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) -{ - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[1]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - if (securityManager.hasInitialized()) { - /* We do not care about the addresses, set the count to 0 */ - whitelistFromBondTable.addr_count = 0; - /* The Nordic SDK will return a failure if we set pp_addr to NULL */ - whitelistFromBondTable.pp_addrs = addressPtr; - /* We want all the IRKs we can get because we do not know which ones match the addresses */ - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - /* Use the security manager to get the IRKs from the bond table */ - ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - return error; - } - } else { - /** - * If there is no security manager then we cannot access the bond table, - * so disable IRK matching - */ - whitelistFromBondTable.addr_count = 0; - whitelistFromBondTable.irk_count = 0; - } - - /** - * For every private resolvable address in the local whitelist check if - * there is an IRK for said address in the bond table and add it to the - * local IRK list. - */ - whitelist.irk_count = 0; - whitelist.addr_count = 0; - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - /* Test if there is a matching IRK for this private resolvable address */ - for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) { - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) { - /* Found the corresponding IRK, add it to our local whitelist */ - whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j]; - whitelist.irk_count++; - /* Make sure we do not look at this IRK again */ - if (j != whitelistFromBondTable.irk_count - 1) { - /** - * This is not the last IRK, so replace the pointer - * with the last pointer in the array - */ - whitelistFromBondTable.pp_irks[j] = - whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1]; - } - /** - * If the IRK is the last pointer in the array simply - * decrement the total IRK count - */ - whitelistFromBondTable.irk_count--; - break; - } - } - } else { - /* Include the address into the whitelist */ - whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i]; - whitelist.addr_count++; - } - } - - return BLE_ERROR_NONE; -} -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - -/** - * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. - * - * Gap::setWhitelist provides the base for preparation of these settings. - * This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table. - * Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice) - * are passed to the identities list (intended to be passed to the Softdevice). - * - * @param[out] gapAdrHelper Reference to the struct for storing settings. - */ - -ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - pm_peer_id_t peer_id; - - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - - uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE]; - - memset(irk_found, 0x00, sizeof(irk_found)); - - - gapAdrHelper.identities_cnt = 0; - - - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager(); - - /** - * Build identities list: - * For every private resolvable address in the bond table check if - * there is maching address in th provided whitelist. - */ - while (peer_id != PM_PEER_ID_INVALID) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) - { - - //ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info; - if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info)) - { - // Copy data to the buffer. - memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - gapAdrHelper.identities_cnt++; - - irk_found[i] = 1; // don't look at this address again - } - } - } - } - } - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - gapAdrHelper.addrs_cnt = 0; - - /** - * Build whitelist from the rest of addresses (explicit addresses) - */ - for (uint8_t i = 0; i < whitelistAddressesSize; ++i) - { - if (!irk_found[i]) - { - memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t)); - gapAdrHelper.addrs[i].addr_id_peer = 0; - gapAdrHelper.addrs_cnt++; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - uint32_t retc; - - if (gapAdrHelper.identities_cnt == 0) { - retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); - } else { - ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i) - { - pp_identities[i] = &gapAdrHelper.identities[i]; - } - - retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); - } - - if (retc == NRF_SUCCESS) { - if (gapAdrHelper.addrs_cnt == 0) { - retc = sd_ble_gap_whitelist_set(NULL, 0); - } else { - ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i) - { - pp_addrs[i] = &gapAdrHelper.addrs[i]; - } - - retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); - } - } - - switch(retc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared. - case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared. - return BLE_ERROR_ALREADY_INITIALIZED; - - case NRF_ERROR_INVALID_ADDR: - case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied. - case NRF_ERROR_DATA_SIZE: - case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() -{ - GapWhiteAndIdentityList_t whiteAndIdentityList; - uint32_t err; - - err = getStackWhiteIdentityList(whiteAndIdentityList); - - if (err != BLE_ERROR_NONE) { - return (ble_error_t)err; - } - - return applyWhiteIdentityList(whiteAndIdentityList); -} -#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h index 05ccc2d863..b328cf5316 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h @@ -148,39 +148,6 @@ private: uint8_t whitelistAddressesSize; ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE]; -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * An internal function used to populate the ble_gap_whitelist_t that will be used by - * the SoftDevice for filtering requests. This function is needed because for the BLE - * API the whitelist is just a collection of keys, but for the stack it also includes - * the IRK table. - */ - ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist); -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - /* internal type for passing a whitelist and a identities list. */ - typedef struct - { - ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; - uint32_t addrs_cnt; - - ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - uint32_t identities_cnt; - } GapWhiteAndIdentityList_t; - - /* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/ - ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/ - ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice. - * - * This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */ - ble_error_t updateWhiteAndIdentityListInStack(void); -#endif - private: bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ Timeout radioNotificationTimeout; From 31f8cd18f7f6905af9afae9915bf8f047cf79a10 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 10:56:35 +0100 Subject: [PATCH 218/274] Nordic BLE: Backport Gap from nRF5 --- .../TARGET_NRF5x/source/nRF5xGap.cpp | 536 +++++++++++++++--- .../TARGET_NRF5x/source/nRF5xGap.h | 60 +- 2 files changed, 502 insertions(+), 94 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp index 5f701aa133..0013890e7f 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp @@ -25,18 +25,116 @@ #include "common/common.h" #include "ble_advdata.h" #include "headers/ble_hci.h" +#include "ble/pal/ConnectionEventMonitor.h" +#include "nRF5xPalSecurityManager.h" -#if (NRF_SD_BLE_API_VERSION >= 3) - #include "peer_manager.h" - #include "peer_data_storage.h" +using ble::pal::vendor::nordic::nRF5xSecurityManager; +typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; +using ble::ArrayView; +using ble::pal::advertising_peer_address_type_t; + +namespace { + +nRF5xSecurityManager& get_sm() { + return nRF5xSecurityManager::get_security_manager(); +} + +ble_error_t set_private_resolvable_address() { +#if (NRF_SD_BLE_API_VERSION <= 2) + ble_gap_addr_t addr = { + BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + }; + + sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + return BLE_ERROR_NONE; +#else + ble_gap_privacy_params_t privacy_config = { 0 }; + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; + err = sd_ble_gap_privacy_set(&privacy_config); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; #endif +} +ble_error_t set_private_non_resolvable_address() { +#if (NRF_SD_BLE_API_VERSION <= 2) + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; + sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); +#else + ble_gap_privacy_params_t privacy_config = { 0 }; + uint32_t err = sd_ble_gap_privacy_get(&privacy_config); + if (err) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE; + err = sd_ble_gap_privacy_set(&privacy_config); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; +#endif +} + +bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { + switch (params.getAdvertisingType()) { + case GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED: + case GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED: + return true; + default: + return false; + } +} + +bool is_identity_address(BLEProtocol::AddressType_t address_type) { + switch (address_type) { + case BLEProtocol::AddressType::PUBLIC_IDENTITY: + case BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY: + return true; + default: + return false; + } +} + +BLEProtocol::AddressType_t convert_nordic_address(uint8_t address) { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return BLEProtocol::AddressType::PUBLIC; + } else { + return BLEProtocol::AddressType::RANDOM; + } +} + +BLEProtocol::AddressType_t convert_identity_address(advertising_peer_address_type_t address) { + if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { + return BLEProtocol::AddressType::PUBLIC_IDENTITY; + } else { + return BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY; + } +} + +} // namespace void radioNotificationStaticCallback(bool param) { nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); gap.processRadioNotificationEvent(param); } +nRF5xGap::nRF5xGap() : Gap(), + advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), + scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), + whitelistAddressesSize(0), + whitelistAddresses(), + radioNotificationCallbackParam(false), + radioNotificationTimeout(), + _connection_event_handler(NULL), + _privacy_enabled(false), + _peripheral_privacy_configuration(default_peripheral_privacy_configuration), + _central_privacy_configuration(default_central_privacy_configuration), + _non_private_address_type(BLEProtocol::AddressType::RANDOM) +{ + m_connectionHandle = BLE_CONN_HANDLE_INVALID; +} /**************************************************************************/ /*! @brief Sets the advertising parameters and payload for the device @@ -196,6 +294,28 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) } } + if (_privacy_enabled) { + if (_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + } + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } adv_para.p_whitelist = &whitelist; #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -250,6 +370,7 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) } } + // FIXME: fill the irk list once addresses are resolved by the softdevice. scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ #else @@ -264,6 +385,13 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + if (_privacy_enabled) { + if (_central_privacy_configuration.use_non_resolvable_random_address) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) { return BLE_ERROR_PARAM_OUT_OF_RANGE; @@ -313,6 +441,7 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, const GapScanningParams *scanParamsIn) { ble_gap_addr_t addr; + ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; memcpy(addr.addr, peerAddr, Gap::ADDR_LEN); @@ -352,6 +481,34 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ + if (_privacy_enabled) { + // configure the "whitelist" with the IRK associated with the identity + // address in input. + if (is_identity_address(peerAddrType)) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t i; + for (i = 0; i < entries.size(); ++i) { + const ble::address_t& entry_address = entries[i].peer_identity_address; + + // entry found; fill the whitelist and invalidate addr_ptr + if (memcmp(entry_address.data(), peerAddr, entry_address.size_) == 0) { + whitelist.pp_irks[0] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + whitelist.irk_count = 1; + scanParams.selective = 1; + addr_ptr = NULL; + break; + } + } + + // Occur only if the address in input hasn't been resolved. + if (i == entries.size()) { + return BLE_ERROR_INVALID_PARAM; + } + } + + set_private_resolvable_address(); + } #else /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -384,9 +541,9 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } #if NRF_SD_BLE_API_VERSION >= 5 - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams, NRF_CONNECTION_TAG); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams, NRF_CONNECTION_TAG); #else - uint32_t rc = sd_ble_gap_connect(&addr, &scanParams, &connParams); + uint32_t rc = sd_ble_gap_connect(addr_ptr, &scanParams, &connParams); #endif if (rc == NRF_SUCCESS) { return BLE_ERROR_NONE; @@ -499,7 +656,6 @@ ble_error_t nRF5xGap::reset(void) /* Clear the internal whitelist */ whitelistAddressesSize = 0; - return BLE_ERROR_NONE; } @@ -542,103 +698,75 @@ uint16_t nRF5xGap::getConnectionHandle(void) /**************************************************************************/ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) { -#if (NRF_SD_BLE_API_VERSION <= 2) - uint8_t cycle_mode; -#else - ble_gap_privacy_params_t privacy_params = {0}; -#endif + using BLEProtocol::AddressType; + if (type != AddressType::PUBLIC || type != AddressType::RANDOM_STATIC) { + return BLE_ERROR_INVALID_PARAM; + } + + if (_privacy_enabled) { + return BLE_ERROR_INVALID_STATE; + } ble_gap_addr_t dev_addr; + memcpy(dev_addr.addr, address, ADDR_LEN); + if (type == AddressType::PUBLIC) { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + } else { + dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; + } - /* When using Public or Static addresses, the cycle mode must be None. - When using Random Private addresses, the cycle mode must be Auto. - In auto mode, the given address is ignored. - */ - if ((type == BLEProtocol::AddressType::PUBLIC) || (type == BLEProtocol::AddressType::RANDOM_STATIC)) - { - memcpy(dev_addr.addr, address, ADDR_LEN); -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE; +#if (NRF_SD_BLE_API_VERSION <= 2) + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr); #else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - dev_addr.addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - } - else if ((type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) || (type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE)) - { -#if (NRF_SD_BLE_API_VERSION <= 2) - cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO; -#else - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - privacy_params.private_addr_type = type; - - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); -#endif - // address is ignored when in auto mode - } - else - { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - dev_addr.addr_type = type; - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + uint32_t err = sd_ble_gap_addr_set(&dev_addr); #endif - return BLE_ERROR_NONE; + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_INVALID_PARAM; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + default: + return BLE_ERROR_UNSPECIFIED; + } } ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) { - ble_gap_addr_t dev_addr; - ble_gap_irk_t irk = {0}; - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.p_device_irk = &irk; + // FIXME: check if privacy is enabled ? + if (typeP == NULL || address == NULL) { + return BLE_ERROR_INVALID_PARAM; + } + ble_gap_addr_t dev_addr; #if (NRF_SD_BLE_API_VERSION <= 2) if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } #else - // Check privacy mode - if( pm_privacy_get(&privacy_params) != NRF_SUCCESS) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } - - // If in private mode, the address is generated by softdevice, so return a nulled address with correct type - if( privacy_params.privacy_mode == BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY ) - { - memset(address, 0, ADDR_LEN); - switch( privacy_params.private_addr_type ) - { - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: - *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE; - break; - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE: - default: - *typeP = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE; - break; - } - return BLE_ERROR_NONE; - } - - // Otherwise recover public/static address if (sd_ble_gap_addr_get(&dev_addr) != NRF_SUCCESS) { +#endif return BLE_ERROR_PARAM_OUT_OF_RANGE; } -#endif - if (typeP != NULL) { - *typeP = static_cast(dev_addr.addr_type); - } - if (address != NULL) { - memcpy(address, dev_addr.addr, ADDR_LEN); + switch (dev_addr.addr_type) { + case BLE_GAP_ADDR_TYPE_PUBLIC: + *typeP = BLEProtocol::AddressType::PUBLIC; + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + *typeP = BLEProtocol::AddressType::RANDOM_STATIC; + break; + + default: + return BLE_ERROR_INVALID_STATE; } + + memcpy(address, dev_addr.addr, ADDR_LEN); return BLE_ERROR_NONE; } @@ -988,5 +1116,247 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } +ble_error_t nRF5xGap::enablePrivacy(bool enable_privacy) +{ + if (enable_privacy == _privacy_enabled) { + return BLE_ERROR_NONE; + } + + ble_error_t err = BLE_ERROR_UNSPECIFIED; + if (enable_privacy == false) { + err = setAddress(_non_private_address_type, _non_private_address); + } else { + err = getAddress(&_non_private_address_type, _non_private_address); + } + + if (err) { + return err; + } + +#if (NRF_SD_BLE_API_VERSION > 2) + ble_gap_privacy_params_t privacy_config = { 0 }; + if (sd_ble_gap_privacy_get(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.privacy_mode = enable_privacy ? + BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY : + BLE_GAP_PRIVACY_MODE_OFF; + if (sd_ble_gap_privacy_set(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } +#endif + + _privacy_enabled = enable_privacy; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration +) { + _peripheral_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration +) { + *configuration = _peripheral_privacy_configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration +) { + _central_privacy_configuration = *configuration; + return BLE_ERROR_NONE; +} + +ble_error_t nRF5xGap::getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration +) { + *configuration = _central_privacy_configuration; + return BLE_ERROR_NONE; +} + +void nRF5xGap::set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler +) { + _connection_event_handler = connection_event_handler; +} + +void nRF5xGap::processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason +) { + if (_connection_event_handler) { + _connection_event_handler->on_disconnected( + handle, + reason + ); + } + + ::Gap::processDisconnectionEvent( + handle, + reason + ); +} + +void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { + using BLEProtocol::AddressType; + + // set the new connection handle as the _default_ handle in gap + setConnectionHandle(handle); + + // deal with own address + AddressType_t own_addr_type; + Address_t own_address; + const uint8_t* own_resolvable_address = NULL; + +#if (NRF_SD_BLE_API_VERSION <= 2) + if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { + own_addr_type = AddressType::PUBLIC; + } else { + own_addr_type = AddressType::RANDOM; + } + memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); +#else + // FIXME: handle privacy ??? + getAddress(&own_addr_type, own_address); +#endif + + if (_privacy_enabled) { + own_resolvable_address = own_address; + } + + // deal with the peer address: If privacy is enabled then the softdevice + // indicates if the address has been resolved or not. If the address has + // been resolved then the identity address should be passed to the application. + // Depending on the privacy chosen by the application, connection request + // from privacy enabled peers may trigger a disconnection, the pairing procedure + // or the authentication procedure. + AddressType_t peer_addr_type; + const uint8_t* peer_address; + const uint8_t* peer_resolvable_address; + +#if (NRF_SD_BLE_API_VERSION <= 2) + bool private_peer_known = evt.irk_match; +#else + bool private_peer_known = evt.peer_addr.addr_id_peer; +#endif + if (private_peer_known) { + // FIXME: Is this correct for SD > 2 ? + const resolving_list_entry_t* entry = get_sm().resolve_address( + evt.peer_addr.addr + ); + MBED_ASSERT(entry == NULL); + + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + peer_address = entry->peer_identity_address.data(); + peer_resolvable_address = evt.peer_addr.addr; + } else { + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + get_sm().get_resolving_list().size() > 0 + ) { + // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible + // with the softdevice ... + sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + return; + } + + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + peer_address = evt.peer_addr.addr; + peer_resolvable_address = NULL; + } + + // notify internal event handler before applying the resolution strategy + if (_connection_event_handler) { + _connection_event_handler->on_connected( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)) + ); + } + + // Apply authentication strategy before application notification + if (!private_peer_known && + _privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE + ) { + switch (_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle); + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + // FIXME: lookup secure DB to know what to do. + break; + + default: + break; + } + } + + processConnectionEvent( + handle, + static_cast(evt.role), + peer_addr_type, + peer_address, + own_addr_type, + own_address, + reinterpret_cast(&(evt.conn_params)), + peer_resolvable_address, + own_resolvable_address + ); +} + +void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { + using BLEProtocol::AddressType; + + AddressType_t peer_addr_type; + const uint8_t* peer_address = evt.peer_addr.addr; + + if (_privacy_enabled && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE + ) { + using ble::pal::vendor::nordic::nRF5xSecurityManager; + + const resolving_list_entry_t* entry = get_sm().resolve_address( + peer_address + ); + + if (entry) { + peer_address = entry->peer_identity_address.data(); + peer_addr_type = convert_identity_address(entry->peer_identity_address_type); + } else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } else { + // filter out the packet. + return; + } + } else { + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + } + + processAdvertisementReport( + peer_address, + evt.rssi, + evt.scan_rsp, + static_cast(evt.type), + evt.dlen, + evt.data, + peer_addr_type + ); +} + diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h index b328cf5316..622588670d 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.h @@ -44,6 +44,7 @@ #include "ble/GapAdvertisingData.h" #include "ble/Gap.h" #include "ble/GapScanningParams.h" +#include "ble/pal/ConnectionEventMonitor.h" #include "nrf_soc.h" @@ -52,8 +53,6 @@ extern "C" { #include "app_util_platform.h" } -#include "btle_security.h" - void radioNotificationStaticCallback(bool param); /**************************************************************************/ @@ -62,9 +61,11 @@ void radioNotificationStaticCallback(bool param); */ /**************************************************************************/ -class nRF5xGap : public Gap -{ +class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor { public: + nRF5xGap(); + + virtual ~nRF5xGap() { } /* Functions that must be implemented from Gap */ virtual ble_error_t setAddress(AddressType_t type, const Address_t address); virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); @@ -129,6 +130,23 @@ public: return BLE_ERROR_UNSPECIFIED; } + virtual ble_error_t enablePrivacy(bool enable); + + virtual ble_error_t setPeripheralPrivacyConfiguration( + const PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getPeripheralPrivacyConfiguration( + PeripheralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t setCentralPrivacyConfiguration( + const CentralPrivacyConfiguration_t *configuration + ); + + virtual ble_error_t getCentralPrivacyConfiguration( + CentralPrivacyConfiguration_t *configuration + ); /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); @@ -229,22 +247,42 @@ private: radioNotificationTimeout.attach_us(mbed::callback(this, &nRF5xGap::postRadioNotificationCallback), 0); } friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */ +public: + /** @note Implements ConnectionEventMonitor. + * @copydoc ConnectionEventMonitor::set_connection_event_handler + */ + virtual void set_connection_event_handler( + ConnectionEventMonitor::EventHandler* connection_event_handler + ); + + /** + * @copydoc ::Gap::processDisconnectionEvent + */ + void processDisconnectionEvent( + Handle_t handle, + DisconnectionReason_t reason + ); private: + friend void btle_handler(const ble_evt_t *p_ble_evt); + friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); + + void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt); + void on_advertising_packet(const ble_gap_evt_adv_report_t &evt); uint16_t m_connectionHandle; + ConnectionEventMonitor::EventHandler* _connection_event_handler; + + bool _privacy_enabled; + PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; + CentralPrivacyConfiguration_t _central_privacy_configuration; + AddressType_t _non_private_address_type; + Address_t _non_private_address; /* * Allow instantiation from nRF5xn when required. */ friend class nRF5xn; - nRF5xGap() : - advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), - scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), - whitelistAddressesSize(0) { - m_connectionHandle = BLE_CONN_HANDLE_INVALID; - } - nRF5xGap(nRF5xGap const &); void operator=(nRF5xGap const &); }; From 167a660ac1f8fa5d1a28322535ae63eb4e978d8e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 10:58:18 +0100 Subject: [PATCH 219/274] Nordic BLE: use pal security manager. --- .../source/btle/btle_security.cpp | 326 ------------ .../TARGET_NRF5x/source/btle/btle_security.h | 146 ------ .../source/btle/btle_security_pm.cpp | 488 ------------------ .../source/nRF5xSecurityManager.h | 194 ------- .../TARGET_NRF5x/source/nRF5xn.cpp | 35 +- .../TARGET_NRF5x/source/nRF5xn.h | 45 +- 6 files changed, 38 insertions(+), 1196 deletions(-) delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp deleted file mode 100644 index 389c9b5c4c..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.cpp +++ /dev/null @@ -1,326 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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. - */ -#if defined(S110) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "pstorage.h" -#include "device_manager.h" -#include "id_manager.h" -} - -#include "btle_security.h" - -static dm_application_instance_t applicationInstance; -static bool initialized = false; -static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result); - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 1, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - if (pstorage_init() != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - dm_init_param_t dm_init_param = { - .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */ - }; - if (dm_init(&dm_init_param) != NRF_SUCCESS) { - return BLE_ERROR_UNSPECIFIED; - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - const dm_application_param_t dm_param = { - .evt_handler = dm_handler, - .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID, - .sec_param = securityParameters - }; - - if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } - - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - dm_handle_t dmHandle = { - .appl_id = applicationInstance, - }; - if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) { - if (rc == NRF_ERROR_NOT_FOUND) { - return BLE_ERROR_INVALID_PARAM; - } else { - return BLE_ERROR_UNSPECIFIED; - } - } - - if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast(securityStatusP))) != NRF_SUCCESS) { - switch (rc) { - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_NO_MEM: - return BLE_ERROR_NO_MEM; - default: - return BLE_ERROR_UNSPECIFIED; - } - } - - return BLE_ERROR_NONE; -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ble_gap_sec_params_t params = securityParameters; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - uint32_t result = sd_ble_gap_authenticate(connectionHandle, ¶ms); - - if (result == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else { - return BLE_ERROR_UNSPECIFIED; - } -} - -ret_code_t -dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - - switch (p_event->event_id) { - case DM_EVT_SECURITY_SETUP: /* started */ { - const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params; - securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - break; - } - case DM_EVT_SECURITY_SETUP_COMPLETE: - securityManager. - processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle, - (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status)); - break; - case DM_EVT_LINK_SECURED: { - unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm; - unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv; - SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - switch (securityMode) { - case 1: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (level) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode); - break; - } - case DM_EVT_DEVICE_CONTEXT_STORED: - securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle); - break; - default: - break; - } - - return NRF_SUCCESS; -} - -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} - - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} -#endif diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h deleted file mode 100644 index a1354a36ee..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security.h +++ /dev/null @@ -1,146 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 _BTLE_SECURITY_H_ -#define _BTLE_SECURITY_H_ - -#include "ble/Gap.h" -#include "ble/SecurityManager.h" - -/** - * Function to test whether the SecurityManager has been initialized. - * Possible by a call to @ref btle_initializeSecurity(). - * - * @return True if the SecurityManager was previously initialized, false - * otherwise. - */ -bool btle_hasInitializedSecurity(void); - -/** - * Enable Nordic's Device Manager, which brings in functionality from the - * stack's Security Manager. The Security Manager implements the actual - * cryptographic algorithms and protocol exchanges that allow two devices to - * securely exchange data and privately detect each other. - * - * @param[in] enableBonding Allow for bonding. - * @param[in] requireMITM Require protection for man-in-the-middle attacks. - * @param[in] iocaps To specify IO capabilities of this peripheral, - * such as availability of a display or keyboard to - * support out-of-band exchanges of security data. - * @param[in] passkey To specify a static passkey. - * - * @return BLE_ERROR_NONE on success. - */ -ble_error_t btle_initializeSecurity(bool enableBonding = true, - bool requireMITM = true, - SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE, - const SecurityManager::Passkey_t passkey = NULL); - -/** - * Get the security status of a link. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[out] securityStatusP - * security status. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP); - -/** - * Set the security mode on a connection. Useful for elevating the security mode - * once certain conditions are met, e.g., a particular service is found. - * - * @param[in] connectionHandle - * Handle to identify the connection. - * @param[in] securityMode - * security mode. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode); - -/** - * Function for deleting all peer device context and all related bonding - * information from the database. - * - * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. - * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or - * application registration. - */ -ble_error_t btle_purgeAllBondingState(void); - -#if (NRF_SD_BLE_API_VERSION <= 2) -/** - * Query the SoftDevice bond table to extract a whitelist containing the BLE - * addresses and IRKs of bonded devices. - * - * @param[in/out] p_whitelist - * (on input) p_whitelist->addr_count and - * p_whitelist->irk_count specify the maximum number of - * addresses and IRKs added to the whitelist structure. - * (on output) *p_whitelist is a whitelist containing the - * addresses and IRKs of the bonded devices. - * - * @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure. - */ -ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist); -#endif - -/** - * Function to test whether a BLE address is generated using an IRK. - * - * @param[in] p_addr - * Pointer to a BLE address. - * @param[in] p_irk - * Pointer to an IRK. - * - * @return True if p_addr can be generated using p_irk, false otherwise. - */ -bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - -/** - * Function to generate a private resolvable BLE address. - * - * @param[out] p_addr - * The output address. - * @param[in] p_irk - * A reference to a IRK. - * - * @note This function does not generate a secure address since the prand number in the - * resolvable address is not truly random. Therefore, the output of this function - * is only meant to be used by the application internally but never exported. - */ -void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address); - -#if (NRF_SD_BLE_API_VERSION >= 3) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList); -#endif - -#endif /* _BTLE_SECURITY_H_ */ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp deleted file mode 100644 index cdc5eba3d9..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_security_pm.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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. - */ - -#if defined(S130) || defined(S132) || defined(S140) -#include "btle.h" - -#include "nRF5xn.h" - -extern "C" { -#include "peer_manager.h" -#include "id_manager.h" -#include "fds.h" -} - -#include "btle_security.h" - -extern "C" void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash); - -static bool initialized = false; - -static void pm_handler(pm_evt_t const *p_event); -static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing. -volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API. - -// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11. -static ble_gap_sec_params_t securityParameters = { - .bond = true, /**< Perform bonding. */ - .mitm = true, /**< Man In The Middle protection required. */ - .lesc = false, /**< Enable LE Secure Connection pairing. */ - .keypress = false, /**< Enable generation of keypress notifications. */ - .io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */ - .oob = 0, /**< Out Of Band data available. */ - .min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */ - .max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */ - .kdist_own = { - .enc = 0, /**< Long Term Key and Master Identification. */ - .id = 0, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - }, /**< Key distribution bitmap: keys that the local device will distribute. */ - .kdist_peer = { - .enc = 1, /**< Long Term Key and Master Identification. */ - .id = 1, /**< Identity Resolving Key and Identity Address Information. */ - .sign = 0, /**< Connection Signature Resolving Key. */ - .link = 0 /**< Derive the Link Key from the LTK. */ - } /**< Key distribution bitmap: keys that the peripheral device will distribute. */ -}; - -bool -btle_hasInitializedSecurity(void) -{ - return initialized; -} - - -ble_error_t -btle_initializeSecurity(bool enableBonding, - bool requireMITM, - SecurityManager::SecurityIOCapabilities_t iocaps, - const SecurityManager::Passkey_t passkey) -{ - /* guard against multiple initializations */ - if (initialized) { - return BLE_ERROR_NONE; - } - - ret_code_t rc; - if (passkey) { - ble_opt_t opts; - opts.gap_opt.passkey.p_passkey = const_cast(passkey); - if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_ADDR: - case NRF_ERROR_INVALID_PARAM: - default: - return BLE_ERROR_INVALID_PARAM; - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - case NRF_ERROR_BUSY: - return BLE_STACK_BUSY; - } - } - } - - // update default security parameters with function call parameters - securityParameters.bond = enableBonding; - securityParameters.mitm = requireMITM; - securityParameters.io_caps = iocaps; - - if (enableBonding) { - securityParameters.kdist_own.enc = 1; - securityParameters.kdist_own.id = 1; - } else { - securityParameters.kdist_own.enc = 0; - securityParameters.kdist_own.id = 0; - } - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_register(pm_handler); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } - - - initialized = true; - return BLE_ERROR_NONE; -} - -ble_error_t -btle_purgeAllBondingState(void) -{ - ret_code_t rc; - - async_ret_code = NRF_ERROR_BUSY; - - rc = pm_peers_delete(); // it is asynhronous API - - if (rc == NRF_SUCCESS) - { - // waiting for respond from pm_handler - while (async_ret_code == NRF_ERROR_BUSY) { - // busy-loop - } - - rc = async_ret_code; - } - - switch (rc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) -{ - ret_code_t rc; - pm_conn_sec_status_t conn_sec_status; - - rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status); - - if (rc == NRF_SUCCESS) - { - if (conn_sec_status.encrypted) { - *securityStatusP = SecurityManager::ENCRYPTED; - } - else if (conn_sec_status.connected) { - if (_enc_in_progress) { - *securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS; - } - else { - *securityStatusP = SecurityManager::NOT_ENCRYPTED; - } - } - - return BLE_ERROR_NONE; - } - - switch (rc) { - case BLE_ERROR_INVALID_CONN_HANDLE: - return BLE_ERROR_INVALID_PARAM; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t -btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) -{ - // use default and updated parameters as starting point - // and modify structure based on security mode. - ret_code_t rc; - - switch (securityMode) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: - /**< Require no protection, open link. */ - securityParameters.bond = false; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 0; - break; - - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: - /**< Require encryption, but no MITM protection. */ - securityParameters.bond = true; - securityParameters.mitm = false; - securityParameters.kdist_own.enc = 1; - break; - - // not yet implemented security modes - case SecurityManager::SECURITY_MODE_NO_ACCESS: - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: - /**< Require encryption and MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: - /**< Require signing or encryption, but no MITM protection. */ - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: - /**< Require signing or encryption, and MITM protection. */ - default: - return BLE_ERROR_NOT_IMPLEMENTED; - } - - // update security settings for given connection - - rc = pm_sec_params_set(&securityParameters); - - if (rc == NRF_SUCCESS) { - rc = pm_conn_secure(connectionHandle, false); - } - - switch (rc) { - case NRF_SUCCESS: - initialized = true; - return BLE_ERROR_NONE; - - case NRF_ERROR_INVALID_STATE: - return BLE_ERROR_INVALID_STATE; - - case NRF_ERROR_INVALID_PARAM: - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - - -void pm_handler(pm_evt_t const *p_event) -{ - nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); - ret_code_t err_code; - SecurityManager::SecurityMode_t resolvedSecurityMode; - - switch (p_event->evt_id) { - case PM_EVT_CONN_SEC_START: /* started */ { - const ble_gap_sec_params_t *peerParams = &securityParameters; - securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle, - peerParams->bond, - peerParams->mitm, - (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps); - _enc_in_progress = true; - break; - } - case PM_EVT_CONN_SEC_SUCCEEDED: - // Update the rank of the peer. - if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) - { - err_code = pm_peer_rank_highest(p_event->peer_id); - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, - SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t - - ble_gap_conn_sec_t conn_sec; - sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec); - - resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS; - - switch (conn_sec.sec_mode.sm) { - case 1: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM; - break; - case 3: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM; - break; - } - break; - case 2: - switch (conn_sec.sec_mode.lv) { - case 1: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM; - break; - case 2: - resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM; - break; - } - break; - } - - securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode); - - _enc_in_progress = false; - break; - - case PM_EVT_CONN_SEC_FAILED: - SecurityManager::SecurityCompletionStatus_t securityCompletionStatus; - - if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) { - securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED; - } else { - securityCompletionStatus = - (SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error; - } - - securityManager. - processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus); - - _enc_in_progress = false; - break; - - case PM_EVT_BONDED_PEER_CONNECTED: - pm_peer_rank_highest(p_event->peer_id); - break; - - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - securityManager.processSecurityContextStoredEvent(p_event->conn_handle); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - break; - - case PM_EVT_PEERS_DELETE_SUCCEEDED: - async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_PEERS_DELETE_FAILED: - async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState - break; - - case PM_EVT_STORAGE_FULL: - // Run garbage collection on the flash. - err_code = fds_gc(); - if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) - { - // Retry. - } - else - { - APP_ERROR_CHECK(err_code); - } - break;//PM_EVT_STORAGE_FULL - - case PM_EVT_CONN_SEC_CONFIG_REQ:{ - // A connected peer (central) is trying to pair, but the Peer Manager already has a bond - // for that peer. Setting allow_repairing to false rejects the pairing request. - // If this event is ignored (pm_conn_sec_config_reply is not called in the event - // handler), the Peer Manager assumes allow_repairing to be false. - pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; - pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config); - } - break;//PM_EVT_CONN_SEC_CONFIG_REQ - - default: - break; - } -} - -#if (NRF_SD_BLE_API_VERSION <= 2) -ble_error_t -btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist) -{ - if (!btle_hasInitializedSecurity()) { - return BLE_ERROR_INITIALIZATION_INCOMPLETE; - } - ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist); - if (err == NRF_SUCCESS) { - return BLE_ERROR_NONE; - } else if (err == NRF_ERROR_NULL) { - return BLE_ERROR_PARAM_OUT_OF_RANGE; - } else { - return BLE_ERROR_INVALID_STATE; - } -} -#endif - -bool -btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - /* - * Use a helper function from the Nordic SDK to test whether the BLE - * address can be generated using the IRK. - */ - return im_address_resolve(p_addr, p_irk); -} - -void -btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address) -{ - /* Set type to resolvable */ - address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; - - /* - * Assign a random number to the most significant 3 bytes - * of the address. - */ - address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E; - address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F; - address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C; - - /* Calculate the hash and store it in the top half of the address */ - ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr); -} - - -#if (NRF_SD_BLE_API_VERSION >= 3) -ble_error_t btle_getAddressesFromBondTable(Gap::Whitelist_t &addrList) -{ - pm_peer_id_t peer_id; - ret_code_t ret; - pm_peer_data_bonding_t bond_data; - - addrList.size = 0; - peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - - /** - * Fill addresses list: - * Copy addresses from bond table, or - * for every private resolvable address in the bond table generate the resolvable address. - */ - while ((peer_id != PM_PEER_ID_INVALID) && (addrList.capacity > addrList.size)) { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pm_peer_data_bonding_load(peer_id, &bond_data); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) { - // Peer data could not be found in flash or peer ID is not valid. - return BLE_ERROR_UNSPECIFIED; - } - - if (bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) { - btle_generateResolvableAddress(bond_data.peer_ble_id.id_info, - (ble_gap_addr_t &) addrList.addresses[addrList.size].address); - } else { - memcpy(&addrList.addresses[addrList.size].address, - &bond_data.peer_ble_id.id_addr_info.addr, - sizeof(addrList.addresses[0].address)); - } - - addrList.addresses[addrList.size].type = static_cast (bond_data.peer_ble_id.id_addr_info.addr_type); - - addrList.size++; - - // get next peer id - peer_id = pm_next_peer_id_get(peer_id); - } - - return BLE_ERROR_NONE; -} -#endif - -#endif // defined(S130) || defined(S132) || defined(S140) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h deleted file mode 100644 index 0e901b5701..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xSecurityManager.h +++ /dev/null @@ -1,194 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 __NRF51822_SECURITY_MANAGER_H__ -#define __NRF51822_SECURITY_MANAGER_H__ - -#include - -#include "nRF5xGap.h" -#include "ble/SecurityManager.h" -#include "btle_security.h" - -class nRF5xSecurityManager : public SecurityManager -{ -public: - /* Functions that must be implemented from SecurityManager */ - virtual ble_error_t init(bool enableBonding, - bool requireMITM, - SecurityIOCapabilities_t iocaps, - const Passkey_t passkey) { - return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey); - } - - virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) { - return btle_getLinkSecurity(connectionHandle, securityStatusP); - } - - virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) { - return btle_setLinkSecurity(connectionHandle, securityMode); - } - - virtual ble_error_t purgeAllBondingState(void) { - return btle_purgeAllBondingState(); - } -#if (NRF_SD_BLE_API_VERSION <= 2) - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - uint8_t i; - - ble_gap_whitelist_t whitelistFromBondTable; - ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE]; - ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - /* Initialize the structure so that we get as many addreses as the whitelist can hold */ - whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_addrs = addressPtr; - whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE; - whitelistFromBondTable.pp_irks = irkPtr; - - ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable); - if (error != BLE_ERROR_NONE) { - addresses.size = 0; - return error; - } - - /* Put all the addresses in the structure */ - for (i = 0; i < whitelistFromBondTable.addr_count; ++i) { - if (i >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size = i; - return BLE_ERROR_NONE; - } - memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t)); - } - - /* Update the current address count */ - addresses.size = i; - - /* The assumption here is that the underlying implementation of - * createWhitelistFromBondTable() will not return the private resolvable - * addresses (which is the case in the SoftDevice). Rather it returns the - * IRKs, so we need to generate the private resolvable address by ourselves. - */ - for (i = 0; i < whitelistFromBondTable.irk_count; ++i) { - if (i + addresses.size >= addresses.capacity) { - /* Ran out of space in the output Gap::Whitelist_t */ - addresses.size += i; - return BLE_ERROR_NONE; - } - btle_generateResolvableAddress( - *whitelistFromBondTable.pp_irks[i], - (ble_gap_addr_t &) addresses.addresses[i + addresses.size] - ); - } - - /* Update the current address count */ - addresses.size += i; - - return BLE_ERROR_NONE; - } -#else // -> NRF_SD_BLE_API_VERSION >= 3 - /** - * @brief Returns a list of addresses from peers in the stacks bond table. - * - * @param[in/out] addresses - * (on input) @ref Gap::Whitelist_t structure where at - * most addresses.capacity addresses from bonded peers will - * be stored. - * (on output) A copy of the addresses from bonded peers. - * - * @retval BLE_ERROR_NONE if successful. - * @retval BLE_ERROR_UNSPECIFIED Bond data could not be found in flash or is inconsistent. - */ - virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const { - return btle_getAddressesFromBondTable(addresses); - } -#endif // #if (NRF_SD_BLE_API_VERSION <= 2) - - - - /** - * @brief Clear nRF5xSecurityManager's state. - * - * @return - * BLE_ERROR_NONE if successful. - */ - virtual ble_error_t reset(void) - { - if (SecurityManager::reset() != BLE_ERROR_NONE) { - return BLE_ERROR_INVALID_STATE; - } - - return BLE_ERROR_NONE; - } - - bool hasInitialized(void) const { - return btle_hasInitializedSecurity(); - } - -public: - /* - * Allow instantiation from nRF5xn when required. - */ - friend class nRF5xn; - - nRF5xSecurityManager() { - /* empty */ - } - -private: - nRF5xSecurityManager(const nRF5xSecurityManager &); - const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &); - -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * Expose an interface that allows us to query the SoftDevice bond table - * and extract a whitelist. - */ - ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const { - return btle_createWhitelistFromBondTable(&whitelistFromBondTable); - } -#endif - /* - * Given a BLE address and a IRK this function check whether the address - * can be generated from the IRK. To do so, this function uses the hash - * function and algorithm described in the Bluetooth low Energy - * Specification. Internally, Nordic SDK functions are used. - */ - bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const { - return btle_matchAddressAndIrk(address, irk); - } - - /* - * Give nRF5xGap access to createWhitelistFromBondTable() and - * matchAddressAndIrk() - */ - friend class nRF5xGap; -}; - -#endif // ifndef __NRF51822_SECURITY_MANAGER_H__ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp index d2df994da1..c9225df634 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.cpp @@ -62,8 +62,7 @@ nRF5xn::nRF5xn(void) : instanceID(BLE::DEFAULT_INSTANCE), gapInstance(), gattServerInstance(NULL), - gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())), - securityManagerInstance(NULL) + gattClient(&(ble::pal::vendor::nordic::nRF5xGattClient::get_client())) { } @@ -187,13 +186,6 @@ ble_error_t nRF5xn::shutdown(void) } } - if (securityManagerInstance != NULL) { - error = securityManagerInstance->reset(); - if (error != BLE_ERROR_NONE) { - return error; - } - } - /* S110 does not support BLE client features, nothing to reset. */ #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) error = getGattClient().reset(); @@ -214,6 +206,31 @@ ble_error_t nRF5xn::shutdown(void) return BLE_ERROR_NONE; } +SecurityManager& nRF5xn::getSecurityManager() +{ + const nRF5xn* self = this; + return const_cast(self->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 { + virtual void set_signing_event_handler(EventHandler *signing_event_handler) { } + } dummy_signing_event_monitor; + + static ble::generic::GenericSecurityManager m_instance( + m_pal, + m_db, + const_cast(getGap()), + dummy_signing_event_monitor + ); + + return m_instance; +} + void nRF5xn::waitForEvent(void) { diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h index 154b9e49dc..b78c77a9f0 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xn.h @@ -21,10 +21,13 @@ #include "ble/blecommon.h" #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" #include "nRF5xGap.h" #include "nRF5xGattServer.h" -#include "nRF5xSecurityManager.h" #include "btle.h" @@ -82,18 +85,14 @@ public: } /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A reference to GattServer. + * @see BLEInstanceBase::getSecurityManager */ - virtual nRF5xSecurityManager &getSecurityManager() { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } + virtual SecurityManager &getSecurityManager(); + + /** + * @see BLEInstanceBase::getSecurityManager + */ + virtual const SecurityManager &getSecurityManager() const; /** * Accessors to GAP. This function checks whether gapInstance points to an @@ -130,23 +129,6 @@ public: return *gattServerInstance; }; - /** - * Accessors to Security Manager. This function checks whether a SecurityManager - * object was previously instantiated. If such object does not exist, then - * it is created before returning. - * - * @return A const reference to GattServer. - * - * @note The accessor is able to modify the object's state because the - * internal pointer has been declared mutable. - */ - virtual const nRF5xSecurityManager &getSecurityManager() const { - if (securityManagerInstance == NULL) { - securityManagerInstance = new nRF5xSecurityManager(); - } - return *securityManagerInstance; - } - virtual void waitForEvent(void); virtual void processEvents(); @@ -170,10 +152,7 @@ private: * it can be assigned inside a 'const' function. */ ble::generic::GenericGattClient gattClient; - mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance. - * If NULL, then SecurityManager has not been initialized. - * The pointer has been declared as 'mutable' so that - * it can be assigned inside a 'const' function. */ + }; #endif From 6f24078507336a3c96c02e92afd65ff1a361510e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 11:00:30 +0100 Subject: [PATCH 220/274] Nordic BLE: route event handling correctly. --- .../TARGET_NRF5x/source/btle/btle.cpp | 57 ++++--------------- 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index 62b5233233..312cf945c5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -272,6 +272,7 @@ void btle_handler(const ble_evt_t *p_ble_evt) (void)p_context; // Keep compiler happy #endif using ble::pal::vendor::nordic::nRF5xGattClient; + using ble::pal::vendor::nordic::nRF5xSecurityManager; // In SDK14+, all other modules from the SDK will be registered independently as softdevice events observers #if !NRF_SDK14PLUS_EVENT_HANDLERS @@ -299,42 +300,16 @@ void btle_handler(const ble_evt_t *p_ble_evt) nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE); nRF5xGap &gap = (nRF5xGap &) ble.getGap(); nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer(); - nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager(); + nRF5xSecurityManager &securityManager = nRF5xSecurityManager::get_security_manager(); /* Custom event handler */ switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: { - Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; -#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110) - /* Only peripheral role is supported by S110 */ - Gap::Role_t role = Gap::PERIPHERAL; -#else - Gap::Role_t role = static_cast(p_ble_evt->evt.gap_evt.params.connected.role); -#endif - gap.setConnectionHandle(handle); - const Gap::ConnectionParams_t *params = reinterpret_cast(&(p_ble_evt->evt.gap_evt.params.connected.conn_params)); - const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr; -#if (NRF_SD_BLE_API_VERSION <= 2) - const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr; - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - static_cast(own->addr_type), own->addr, - params); -#else - Gap::AddressType_t addr_type; - Gap::Address_t own_address; - gap.getAddress(&addr_type, own_address); - - gap.processConnectionEvent(handle, - role, - static_cast(peer->addr_type), peer->addr, - addr_type, own_address, - params); -#endif + case BLE_GAP_EVT_CONNECTED: + gap.on_connection( + p_ble_evt->evt.gap_evt.conn_handle, + p_ble_evt->evt.gap_evt.params.connected + ); break; - } case BLE_GAP_EVT_DISCONNECTED: { Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle; @@ -416,10 +391,6 @@ void btle_handler(const ble_evt_t *p_ble_evt) } #endif - case BLE_GAP_EVT_PASSKEY_DISPLAY: - securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey); - break; - case BLE_GAP_EVT_TIMEOUT: gap.processTimeoutEvent(static_cast(p_ble_evt->evt.gap_evt.params.timeout.src)); break; @@ -431,21 +402,17 @@ void btle_handler(const ble_evt_t *p_ble_evt) // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION)); break; - case BLE_GAP_EVT_ADV_REPORT: { - const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report; - gap.processAdvertisementReport(advReport->peer_addr.addr, - advReport->rssi, - advReport->scan_rsp, - static_cast(advReport->type), - advReport->dlen, - advReport->data); + case BLE_GAP_EVT_ADV_REPORT: + gap.on_advertising_packet(p_ble_evt->evt.gap_evt.params.adv_report); break; - } default: break; } + // Process security manager events + securityManager.sm_handler(p_ble_evt); + gattServer.hwCallback(p_ble_evt); } From dd6a5350e24f21b2bbb7ef93751367c32a90dd0b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 11:24:26 +0100 Subject: [PATCH 221/274] Nordic BLE: Remove peer manager handling. --- .../TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index 312cf945c5..0adbf3d771 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -232,9 +232,6 @@ error_t btle_init(void) } #endif - // Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp) - pm_init(); - #if (NRF_SD_BLE_API_VERSION <= 2) ble_gap_addr_t addr; if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) { @@ -243,10 +240,6 @@ error_t btle_init(void) if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) { return ERROR_INVALID_PARAM; } -#else - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - pm_privacy_set(&privacy_params); #endif // From SDK 14 onwards event handlers are registered differently @@ -287,9 +280,6 @@ void btle_handler(const ble_evt_t *p_ble_evt) // Forward BLE events to the Connection State module. // This must be called before any event handler that uses this module. ble_conn_state_on_ble_evt(p_ble_evt); - - // Forward BLE events to the Peer Manager - pm_on_ble_evt(p_ble_evt); #endif #endif From a22b4e5d5e8ac699ec2eb953674e15aa5e4ba1a3 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 11:25:23 +0100 Subject: [PATCH 222/274] Nordic BLE: Remove nordic gap init. This initialization is already done in GattServer. --- .../TARGET_NRF5x/source/btle/btle.cpp | 3 +- .../TARGET_NRF5x/source/btle/btle_gap.cpp | 99 ------------------- .../TARGET_NRF5x/source/btle/btle_gap.h | 24 ----- .../TARGET_SOFTDEVICE_COMMON/ble/README.md | 8 ++ 4 files changed, 9 insertions(+), 125 deletions(-) delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp delete mode 100644 features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index 0adbf3d771..da9da3eb9b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -23,7 +23,6 @@ #include "ble_flash.h" #include "ble_conn_params.h" -#include "btle_gap.h" #include "custom/custom_helper.h" #include "ble/GapEvents.h" @@ -252,7 +251,7 @@ error_t btle_init(void) ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch)); #endif - return btle_gap_init(); + return ERROR_NONE; } #if NRF_SDK14PLUS_EVENT_HANDLERS diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp deleted file mode 100644 index 085fb1e08e..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 "common/common.h" - -#include "headers/ble_gap.h" -#include "ble_conn_params.h" - -static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST; -#if SDK_CONN_PARAMS_MODULE_ENABLE -static void error_callback(uint32_t nrf_error); -#endif // SDK_CONN_PARAMS_MODULE_ENABLE - -/**************************************************************************/ -/*! - @brief Initialise GAP in the underlying SoftDevice - - @returns -*/ -/**************************************************************************/ -error_t btle_gap_init(void) -{ - ble_gap_conn_params_t gap_conn_params = {0}; - - gap_conn_params.min_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MIN_INTERVAL_MS); // in 1.25ms units - gap_conn_params.max_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MAX_INTERVAL_MS); // in 1.25ms unit - gap_conn_params.slave_latency = CFG_GAP_CONNECTION_SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS / 10; // in 10ms unit - - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed - - ASSERT_STATUS( sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) CFG_GAP_LOCAL_NAME, strlen(CFG_GAP_LOCAL_NAME))); - ASSERT_STATUS( sd_ble_gap_appearance_set(CFG_GAP_APPEARANCE)); - ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params)); - ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL)); - - /** - * Call to conn_params_init() is not necessary; and so is disabled by default. - * This API should be exposed to the user to be invoked when necessary. - */ -#if SDK_CONN_PARAMS_MODULE_ENABLE - /* Connection Parameters */ - enum { - FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER), - NEXT_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER), - MAX_UPDATE_COUNT = 3 - }; - - ble_conn_params_init_t cp_init = {0}; - - cp_init.p_conn_params = NULL; - cp_init.first_conn_params_update_delay = FIRST_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = true; - cp_init.evt_handler = NULL; - cp_init.error_handler = error_callback; - - ASSERT_STATUS ( ble_conn_params_init(&cp_init)); -#endif // SDK_CONN_PARAMS_MODULE_ENABLE - - return ERROR_NONE; -} - -/**************************************************************************/ -/*! - @brief Converts msecs to an integer representing 1.25ms units - - @param[in] ms - The number of milliseconds to conver to 1.25ms units - - @returns The number of 1.25ms units in the supplied number of ms -*/ -/**************************************************************************/ -static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) -{ - return (interval_ms * 4) / 5; -} - -#if SDK_CONN_PARAMS_MODULE_ENABLE -static void error_callback(uint32_t nrf_error) -{ - ASSERT_STATUS_RET_VOID( nrf_error ); -} -#endif // SDK_CONN_PARAMS_MODULE_ENABLE diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h deleted file mode 100644 index 828da3cd78..0000000000 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle_gap.h +++ /dev/null @@ -1,24 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 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 _BTLE_GAP_H_ -#define _BTLE_GAP_H_ - -#include "common/common.h" - -error_t btle_gap_init(void); - -#endif // ifndef _BTLE_GAP_H_ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md index c9f238a697..0b7a849b17 100644 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md +++ b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/README.md @@ -7,6 +7,14 @@ components/ble Removed * ble_services/* * ble_dtm/ble_dtm_hw_nrf51.c + * ble_advertising/* + * ble_db_discovery/* + * ble_dtm/* + * ble_racp/* + * common/* + * nrf_ble_gatt/* + * nrf_ble_qwr/* + * peer_manager/* Renamed * #include "ble.h" -> #include "nrf_ble.h" From ca5a9f359a6052817346eecd46a4b403a6917b04 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 11:31:25 +0100 Subject: [PATCH 223/274] Nordic BLE: remove unecessary nordic ble libraries. --- .../TARGET_NRF5x/source/btle/btle.cpp | 23 +- .../TARGET_NRF5x/source/btle/btle.h | 1 - .../TARGET_NRF5x/source/nRF5xGap.cpp | 1 - .../ble/ble_advertising/ble_advertising.c | 695 ---------- .../ble/ble_advertising/ble_advertising.h | 355 ------ .../ble/ble_db_discovery/ble_db_discovery.c | 986 --------------- .../ble/ble_db_discovery/ble_db_discovery.h | 235 ---- .../ble/ble_dtm/ble_dtm.c | 942 -------------- .../ble/ble_dtm/ble_dtm.h | 237 ---- .../ble/ble_dtm/ble_dtm_hw.h | 103 -- .../ble/ble_dtm/ble_dtm_hw_nrf52.c | 128 -- .../ble/ble_racp/ble_racp.c | 87 -- .../ble/ble_racp/ble_racp.h | 135 -- .../ble/common/ble_advdata.c | 706 ----------- .../ble/common/ble_advdata.h | 233 ---- .../ble/common/ble_conn_params.c | 572 --------- .../ble/common/ble_conn_params.h | 156 --- .../ble/common/ble_conn_state.c | 444 ------- .../ble/common/ble_conn_state.h | 317 ----- .../ble/common/ble_date_time.h | 113 -- .../ble/common/ble_gatt_db.h | 89 -- .../ble/common/ble_sensor_location.h | 76 -- .../ble/common/ble_srv_common.c | 237 ---- .../ble/common/ble_srv_common.h | 409 ------ .../ble/nrf_ble_gatt/nrf_ble_gatt.c | 552 -------- .../ble/nrf_ble_gatt/nrf_ble_gatt.h | 242 ---- .../ble/nrf_ble_qwr/nrf_ble_qwr.c | 447 ------- .../ble/nrf_ble_qwr/nrf_ble_qwr.h | 227 ---- .../ble/peer_manager/gatt_cache_manager.c | 568 --------- .../ble/peer_manager/gatt_cache_manager.h | 113 -- .../ble/peer_manager/gatts_cache_manager.c | 340 ----- .../ble/peer_manager/gatts_cache_manager.h | 163 --- .../ble/peer_manager/id_manager.c | 1065 ---------------- .../ble/peer_manager/id_manager.h | 327 ----- .../ble/peer_manager/peer_data_storage.c | 685 ---------- .../ble/peer_manager/peer_data_storage.h | 270 ---- .../ble/peer_manager/peer_database.c | 831 ------------ .../ble/peer_manager/peer_database.h | 306 ----- .../ble/peer_manager/peer_id.c | 202 --- .../ble/peer_manager/peer_id.h | 167 --- .../ble/peer_manager/peer_manager.c | 965 -------------- .../ble/peer_manager/peer_manager.h | 765 ----------- .../ble/peer_manager/peer_manager_internal.h | 207 --- .../ble/peer_manager/peer_manager_types.h | 377 ------ .../ble/peer_manager/pm_buffer.c | 151 --- .../ble/peer_manager/pm_buffer.h | 159 --- .../ble/peer_manager/pm_mutex.c | 144 --- .../ble/peer_manager/pm_mutex.h | 125 -- .../ble/peer_manager/security_dispatcher.c | 1119 ----------------- .../ble/peer_manager/security_dispatcher.h | 164 --- .../ble/peer_manager/security_manager.c | 695 ---------- .../ble/peer_manager/security_manager.h | 179 --- 52 files changed, 10 insertions(+), 18825 deletions(-) delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c delete mode 100644 targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp index da9da3eb9b..09091c8326 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.cpp @@ -21,23 +21,12 @@ #include "btle_clock.h" #include "ble_flash.h" -#include "ble_conn_params.h" #include "custom/custom_helper.h" #include "ble/GapEvents.h" #include "nRF5xn.h" -// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work -#undef STATIC_ASSERT_SIMPLE -#undef STATIC_ASSERT_MSG - -// FIXME : We can't use mbed_assert.h because we're using these macros within functions -#define STATIC_ASSERT_MSG(EXPR, MSG) -#define STATIC_ASSERT_SIMPLE(EXPR) - -#warning FIXME : We can't use mbed_assert.h because we're using these within functions - #ifdef S110 #define IS_LEGACY_DEVICE_MANAGER_ENABLED 1 #elif defined(S130) || defined(S132) @@ -51,8 +40,6 @@ extern "C" { #else #include "nrf_fstorage.h" #include "fds.h" - #include "peer_manager.h" - #include "ble_conn_state.h" #endif #include "nrf_sdh.h" @@ -63,6 +50,16 @@ extern "C" { #include "nRF5xPalGattClient.h" +// This is a C++ file, so C11 _Static_assert (works with -std=gnu99 on GCC) won't work +#undef STATIC_ASSERT_SIMPLE +#undef STATIC_ASSERT_MSG + +// FIXME : We can't use mbed_assert.h because we're using these macros within functions +#define STATIC_ASSERT_MSG(EXPR, MSG) +#define STATIC_ASSERT_SIMPLE(EXPR) + +#warning FIXME : We can't use mbed_assert.h because we're using these within functions + // Make this volatile at it will be set in interrupt context volatile bool isEventsSignaled = false; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h index 9b75ed1714..4c35282d8a 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/btle.h @@ -23,7 +23,6 @@ extern "C" { #include "common/common.h" -#include "ble_srv_common.h" #include "headers/nrf_ble.h" #if NRF_SD_BLE_API_VERSION >= 5 diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp index 0013890e7f..71f40f8b45 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGap.cpp @@ -23,7 +23,6 @@ #include "ble/BLE.h" #include "common/common.h" -#include "ble_advdata.h" #include "headers/ble_hci.h" #include "ble/pal/ConnectionEventMonitor.h" #include "nRF5xPalSecurityManager.h" diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c deleted file mode 100644 index 1cb77cd6c8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.c +++ /dev/null @@ -1,695 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_ADVERTISING) -#include "ble_advdata.h" -#include "ble_advertising.h" -#include "nrf_soc.h" -#include "nrf_log.h" -#include "nrf_fstorage.h" -#include "sdk_errors.h" -#include "nrf_sdh_ble.h" -#include "nrf_sdh_soc.h" - -#define BLE_ADV_MODES (5) /**< Total number of possible advertising modes. */ - - -#if (NRF_SD_BLE_API_VERSION <= 2) - - static bool whitelist_has_entries(ble_advertising_t * const p_advertising) - { - return ((p_advertising->whitelist.addr_count != 0) || (p_advertising->whitelist.irk_count != 0)); - } - -#else - - static bool whitelist_has_entries(ble_advertising_t * const p_advertising) - { - return p_advertising->whitelist_in_use; - } - -#endif - - - -/**@brief Function for checking if an address is valid. - */ -static bool addr_is_valid(uint8_t const * const addr) -{ - for (uint32_t i = 0; i < BLE_GAP_ADDR_LEN; i++) - { - if (addr[i] != 0) - { - return true; - } - } - return false; -} - - -static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode) -{ - return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES); -} - - -/**@brief Function for handling the Connected event. - * - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_connected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH) - { - p_advertising->current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - } -} - - -/**@brief Function for handling the Disconnected event. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - uint32_t ret; - - p_advertising->whitelist_temporarily_disabled = false; - - if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle && - p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false) - { - ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED); - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - } -} - - -/**@brief Function for handling the Timeout event. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_timeout(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt) -{ - ret_code_t ret; - - if (p_ble_evt->evt.gap_evt.params.timeout.src != BLE_GAP_TIMEOUT_SRC_ADVERTISING) - { - // Nothing to do. - return; - } - - // Start advertising in the next mode. - ret = ble_advertising_start(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current)); - - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } -} - - -/** @brief Function to determine if a flash write operation in in progress. - * - * @return true if a flash operation is in progress, false if not. - */ -static bool flash_access_in_progress() -{ - return nrf_fstorage_is_busy(NULL); -} - - -/**@brief Get the next available advertising mode. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] adv_mode Requested advertising mode. - * - * @returns adv_mode if possible, or the best available mode if not. - */ -static ble_adv_mode_t adv_mode_next_avail_get(ble_advertising_t * const p_advertising, - ble_adv_mode_t adv_mode) -{ - bool peer_addr_is_valid = addr_is_valid(p_advertising->peer_address.addr); - - // If a mode is disabled, continue to the next mode. - - switch (adv_mode) - { - case BLE_ADV_MODE_DIRECTED: - if ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid) - { - return BLE_ADV_MODE_DIRECTED; - } - // Fallthrough. - - case BLE_ADV_MODE_DIRECTED_SLOW: - if ((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && peer_addr_is_valid) - { - return BLE_ADV_MODE_DIRECTED_SLOW; - } - // Fallthrough. - - case BLE_ADV_MODE_FAST: - if (p_advertising->adv_modes_config.ble_adv_fast_enabled) - { - return BLE_ADV_MODE_FAST; - } - // Fallthrough. - - case BLE_ADV_MODE_SLOW: - if (p_advertising->adv_modes_config.ble_adv_slow_enabled) - { - return BLE_ADV_MODE_SLOW; - } - // Fallthrough. - - default: - return BLE_ADV_MODE_IDLE; - } -} - - -/**@brief Function for starting directed advertising. - * - * @param[in] p_advertising Advertising instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS - */ -static ret_code_t set_adv_mode_directed(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED; - - p_adv_params->p_peer_addr = &(p_advertising->peer_address); - p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; - p_adv_params->timeout = 0; - p_adv_params->interval = 0; - - return NRF_SUCCESS; -} - - -/**@brief Function for starting directed slow advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS - */ -static ret_code_t set_adv_mode_directed_slow(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - p_advertising->adv_evt = BLE_ADV_EVT_DIRECTED_SLOW; - - p_adv_params->p_peer_addr = &p_advertising->peer_address; - p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_directed_slow_timeout; - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_directed_slow_interval; - - return NRF_SUCCESS; -} - - -/**@brief Function for starting fast advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS or an error from @ref ble_advdata_set(). - */ -static ret_code_t set_adv_mode_fast(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - ret_code_t ret; - - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_fast_interval; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_fast_timeout; - - if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled) && - (whitelist_has_entries(p_advertising))) - { - #if (NRF_SD_BLE_API_VERSION <= 2) - p_adv_params->p_whitelist = &m_whitelist; - #endif - - p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; - p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - p_advertising->adv_evt = BLE_ADV_EVT_FAST_WHITELIST; - } - else - { - p_advertising->adv_evt = BLE_ADV_EVT_FAST; - } - - return NRF_SUCCESS; -} - - -/**@brief Function for starting slow advertising. - * - * @param[in] p_advertising Advertising module instance. - * @param[out] p_adv_params Advertising parameters. - * - * @return NRF_SUCCESS or an error from @ref ble_advdata_set(). - */ -static ret_code_t set_adv_mode_slow(ble_advertising_t * const p_advertising, - ble_gap_adv_params_t * p_adv_params) -{ - ret_code_t ret; - - p_adv_params->interval = p_advertising->adv_modes_config.ble_adv_slow_interval; - p_adv_params->timeout = p_advertising->adv_modes_config.ble_adv_slow_timeout; - - if ((p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled) && - (whitelist_has_entries(p_advertising))) - { - #if (NRF_SD_BLE_API_VERSION <= 2) - { - p_adv_params->p_whitelist = &p_advertising->whitelist; - } - #endif - - p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ; - p_advertising->advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - p_advertising->adv_evt = BLE_ADV_EVT_SLOW_WHITELIST; - } - else - { - p_advertising->adv_evt = BLE_ADV_EVT_SLOW; - } - - return NRF_SUCCESS; -} - - -void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, - uint8_t ble_cfg_tag) -{ - p_advertising->conn_cfg_tag = ble_cfg_tag; -} - - -uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, - ble_advertising_init_t const * const p_init) -{ - uint32_t ret; - if ((p_init == NULL) || (p_advertising == NULL)) - { - return NRF_ERROR_NULL; - } - - p_advertising->initialized = true; - p_advertising->adv_mode_current = BLE_ADV_MODE_IDLE; - p_advertising->adv_modes_config = p_init->config; - p_advertising->conn_cfg_tag = BLE_CONN_CFG_TAG_DEFAULT; - p_advertising->evt_handler = p_init->evt_handler; - p_advertising->error_handler = p_init->error_handler; - p_advertising->current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID; - - memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); - memset(&p_advertising->advdata, 0, sizeof(p_advertising->advdata)); - - // Copy advertising data. - p_advertising->advdata.name_type = p_init->advdata.name_type; - p_advertising->advdata.include_appearance = p_init->advdata.include_appearance; - p_advertising->advdata.flags = p_init->advdata.flags; - p_advertising->advdata.short_name_len = p_init->advdata.short_name_len; - - p_advertising->advdata.uuids_complete = p_init->advdata.uuids_complete; - p_advertising->advdata.uuids_more_available = p_init->advdata.uuids_more_available; - p_advertising->advdata.uuids_solicited = p_init->advdata.uuids_solicited; - p_advertising->advdata.include_ble_device_addr = p_init->advdata.include_ble_device_addr; - - if (p_init->advdata.p_manuf_specific_data != NULL) - { - p_advertising->advdata.p_manuf_specific_data = &(p_advertising->manuf_specific_data); - p_advertising->manuf_specific_data.data.p_data = p_advertising->manuf_data_array; - p_advertising->advdata.p_manuf_specific_data->company_identifier = - p_init->advdata.p_manuf_specific_data->company_identifier; - p_advertising->advdata.p_manuf_specific_data->data.size = p_init->advdata.p_manuf_specific_data->data.size; - - for (uint32_t i = 0; i < p_advertising->advdata.p_manuf_specific_data->data.size; i++) - { - p_advertising->manuf_data_array[i] = p_init->advdata.p_manuf_specific_data->data.p_data[i]; - } - } - - if (p_init->advdata.p_service_data_array != NULL) - { - p_advertising->service_data.data.p_data = p_advertising->service_data_array; - p_advertising->advdata.p_service_data_array = &(p_advertising->service_data); - p_advertising->advdata.p_service_data_array->data.p_data = p_advertising->service_data_array; - p_advertising->advdata.p_service_data_array->data.size = p_init->advdata.p_service_data_array->data.size; - p_advertising->advdata.p_service_data_array->service_uuid = p_init->advdata.p_service_data_array->service_uuid; - - for (uint32_t i = 0; i < p_advertising->advdata.p_service_data_array->data.size; i++) - { - p_advertising->service_data_array[i] = p_init->advdata.p_service_data_array->data.p_data[i]; - } - - p_advertising->advdata.service_data_count = p_init->advdata.service_data_count; - } - - if (p_init->advdata.p_slave_conn_int != NULL) - { - p_advertising->advdata.p_slave_conn_int = &(p_advertising->slave_conn_int); - p_advertising->advdata.p_slave_conn_int->max_conn_interval = p_init->advdata.p_slave_conn_int->max_conn_interval; - p_advertising->advdata.p_slave_conn_int->min_conn_interval = p_init->advdata.p_slave_conn_int->min_conn_interval; - } - - if (p_init->advdata.p_tx_power_level != NULL) - { - p_advertising->advdata.p_tx_power_level = p_init->advdata.p_tx_power_level; - } - -#if (NRF_SD_BLE_API_VERSION <= 2) - for (int i = 0; i whitelist.pp_addrs[i] = &p_advertising->whitelist_addrs[i]; - } - - for (int i = 0; i whitelist.pp_irks[i] = &p_advertising->whitelist_irks[i]; - } -#endif - ret = ble_advdata_set(&(p_advertising->advdata), &(p_init->srdata)); - return ret; -} - - -uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, - ble_adv_mode_t advertising_mode) -{ - uint32_t ret; - ble_gap_adv_params_t adv_params; - - if (p_advertising->initialized == false) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->adv_mode_current = advertising_mode; - - // Delay starting advertising until the flash operations are complete. - if (flash_access_in_progress()) - { - p_advertising->advertising_start_pending = true; - return NRF_SUCCESS; - } - - memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address)); - - if ( ((p_advertising->adv_modes_config.ble_adv_directed_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) - ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED)) - ||((p_advertising->adv_modes_config.ble_adv_directed_slow_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW)) - ) - { - if (p_advertising->evt_handler != NULL) - { - p_advertising->peer_addr_reply_expected = true; - p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST); - } - else - { - p_advertising->peer_addr_reply_expected = false; - } - } - - p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode); - - // Fetch the whitelist. - if ((p_advertising->evt_handler != NULL) && - (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) && - (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) && - (!p_advertising->whitelist_temporarily_disabled)) - { - #if (NRF_SD_BLE_API_VERSION >= 3) - p_advertising->whitelist_in_use = false; - #endif - p_advertising->whitelist_reply_expected = true; - p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST); - } - else - { - p_advertising->whitelist_reply_expected = false; - } - - // Initialize advertising parameters with default values. - memset(&adv_params, 0, sizeof(adv_params)); - - adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; - adv_params.fp = BLE_GAP_ADV_FP_ANY; - - // Set advertising parameters and events according to selected advertising mode. - switch (p_advertising->adv_mode_current) - { - case BLE_ADV_MODE_DIRECTED: - ret = set_adv_mode_directed(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_DIRECTED_SLOW: - ret = set_adv_mode_directed_slow(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_FAST: - ret = set_adv_mode_fast(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_SLOW: - ret = set_adv_mode_slow(p_advertising, &adv_params); - break; - - case BLE_ADV_MODE_IDLE: - p_advertising->adv_evt = BLE_ADV_EVT_IDLE; - break; - - default: - break; - } - - if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE) - { - ret = sd_ble_gap_adv_start(&adv_params, p_advertising->conn_cfg_tag); - if (ret != NRF_SUCCESS) - { - return ret; - } - } - - if (p_advertising->evt_handler != NULL) - { - p_advertising->evt_handler(p_advertising->adv_evt); - } - - return NRF_SUCCESS; -} - - -void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connected(p_advertising, p_ble_evt); - break; - - // Upon disconnection, whitelist will be activated and direct advertising is started. - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected(p_advertising, p_ble_evt); - break; - - // Upon time-out, the next advertising mode is started. - case BLE_GAP_EVT_TIMEOUT: - on_timeout(p_advertising, p_ble_evt); - break; - - default: - break; - } -} - - -void ble_advertising_on_sys_evt(uint32_t evt_id, void * p_context) -{ - ble_advertising_t * p_advertising = (ble_advertising_t *)p_context; - - switch (evt_id) - { - //When a flash operation finishes, re-attempt to start advertising operations. - case NRF_EVT_FLASH_OPERATION_SUCCESS: - case NRF_EVT_FLASH_OPERATION_ERROR: - { - if (p_advertising->advertising_start_pending) - { - p_advertising->advertising_start_pending = false; - ret_code_t ret = ble_advertising_start(p_advertising, - p_advertising->adv_mode_current); - - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - } - } break; - - default: - // No implementation needed. - break; - } -} - - -uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t * p_peer_address) -{ - if (!p_advertising->peer_addr_reply_expected) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->peer_addr_reply_expected = false; - - memcpy(&p_advertising->peer_address, p_peer_address, sizeof(p_advertising->peer_address)); - - return NRF_SUCCESS; -} - - -uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t const * p_gap_addrs, - uint32_t addr_cnt, - ble_gap_irk_t const * p_gap_irks, - uint32_t irk_cnt) -{ - if (!p_advertising->whitelist_reply_expected) - { - return NRF_ERROR_INVALID_STATE; - } - - p_advertising->whitelist_reply_expected = false; - - #if (NRF_SD_BLE_API_VERSION <= 2) - - p_advertising->whitelist.addr_count = addr_cnt; - p_advertising->whitelist.irk_count = irk_cnt; - - for (uint32_t i = 0; i < addr_cnt; i++) - { - *p_advertising->whitelist.pp_addrs[i] = p_gap_addrs[i]; - } - - for (uint32_t i = 0; i < irk_cnt; i++) - { - *p_advertising->whitelist.pp_irks[i] = p_gap_irks[i]; - } - - #else - - p_advertising->whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0)); - - #endif - - return NRF_SUCCESS; -} - - -uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising) -{ - uint32_t ret; - - (void) sd_ble_gap_adv_stop(); - - p_advertising->whitelist_temporarily_disabled = true; - - #if (NRF_SD_BLE_API_VERSION >= 3) - p_advertising->whitelist_in_use = false; - #endif - - p_advertising->advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - - ret = ble_advdata_set(&(p_advertising->advdata), NULL); - if (ret != NRF_SUCCESS) - { - return ret; - } - - ret = ble_advertising_start(p_advertising, p_advertising->adv_mode_current); - if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL)) - { - p_advertising->error_handler(ret); - } - - return NRF_SUCCESS; -} - - -void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, - ble_adv_modes_config_t const * const p_adv_modes_config) -{ - p_advertising->adv_modes_config = *p_adv_modes_config; -} - - -#endif // NRF_MODULE_ENABLED(BLE_ADVERTISING) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h deleted file mode 100644 index 61bbb7b0b6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_advertising/ble_advertising.h +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_advertising Advertising Module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for handling connectable BLE advertising. - * - * @details The Advertising Module handles connectable advertising for your application. It can - * be configured with advertising modes to suit most typical use cases. - * Your main application can react to changes in advertising modes - * if an event handler is provided. - * - * @note The Advertising Module supports only applications with a single peripheral link. - * - */ - -#ifndef BLE_ADVERTISING_H__ -#define BLE_ADVERTISING_H__ - -#include -#include "nrf_error.h" -#include "nrf_ble.h" -#include "ble_gattc.h" -#include "ble_advdata.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a ble_advertising instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define BLE_ADVERTISING_DEF(_name) \ -static ble_advertising_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, \ - BLE_ADV_BLE_OBSERVER_PRIO, \ - ble_advertising_on_ble_evt, &_name); \ -NRF_SDH_SOC_OBSERVER(_name ## _soc_obs, \ - BLE_ADV_SOC_OBSERVER_PRIO, \ - ble_advertising_on_sys_evt, &_name) - - -/**@brief Advertising modes. */ -typedef enum -{ - BLE_ADV_MODE_IDLE, /**< Idle; no connectable advertising is ongoing. */ - BLE_ADV_MODE_DIRECTED, /**< Directed advertising attempts to connect to the most recently disconnected peer. */ - BLE_ADV_MODE_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) attempts to connect to the most recently disconnected peer. */ - BLE_ADV_MODE_FAST, /**< Fast advertising will connect to any peer device, or filter with a whitelist if one exists. */ - BLE_ADV_MODE_SLOW, /**< Slow advertising is similar to fast advertising. By default, it uses a longer advertising interval and time-out than fast advertising. However, these options are defined by the user. */ -} ble_adv_mode_t; - -/**@brief Advertising events. - * - * @details These events are propagated to the main application if a handler was provided during - * initialization of the Advertising Module. Events for modes that are not used can be - * ignored. Similarly, BLE_ADV_EVT_WHITELIST_REQUEST and BLE_ADV_EVT_PEER_ADDR_REQUEST - * can be ignored if whitelist and direct advertising is not used. - */ -typedef enum -{ - BLE_ADV_EVT_IDLE, /**< Idle; no connectable advertising is ongoing.*/ - BLE_ADV_EVT_DIRECTED, /**< Direct advertising mode has started. */ - BLE_ADV_EVT_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) has started. */ - BLE_ADV_EVT_FAST, /**< Fast advertising mode has started. */ - BLE_ADV_EVT_SLOW, /**< Slow advertising mode has started. */ - BLE_ADV_EVT_FAST_WHITELIST, /**< Fast advertising mode using the whitelist has started. */ - BLE_ADV_EVT_SLOW_WHITELIST, /**< Slow advertising mode using the whitelist has started. */ - BLE_ADV_EVT_WHITELIST_REQUEST, /**< Request a whitelist from the main application. For whitelist advertising to work, the whitelist must be set when this event occurs. */ - BLE_ADV_EVT_PEER_ADDR_REQUEST /**< Request a peer address from the main application. For directed advertising to work, the peer address must be set when this event occurs. */ -} ble_adv_evt_t; - -/**@brief Options for the different advertisement modes. - * - * @details This structure is used to enable or disable advertising modes and to configure time-out - * periods and advertising intervals. - */ -typedef struct -{ - bool ble_adv_on_disconnect_disabled; /**< Enable or disable automatic return to advertising upon disconnecting.*/ - bool ble_adv_whitelist_enabled; /**< Enable or disable use of the whitelist. */ - bool ble_adv_directed_enabled; /**< Enable or disable direct advertising mode. */ - bool ble_adv_directed_slow_enabled; /**< Enable or disable direct advertising mode. */ - bool ble_adv_fast_enabled; /**< Enable or disable fast advertising mode. */ - bool ble_adv_slow_enabled; /**< Enable or disable slow advertising mode. */ - uint32_t ble_adv_directed_slow_interval; /**< Advertising interval for directed advertising. */ - uint32_t ble_adv_directed_slow_timeout; /**< Time-out (number of tries) for direct advertising. */ - uint32_t ble_adv_fast_interval; /**< Advertising interval for fast advertising. */ - uint32_t ble_adv_fast_timeout; /**< Time-out (in seconds) for fast advertising. */ - uint32_t ble_adv_slow_interval; /**< Advertising interval for slow advertising. */ - uint32_t ble_adv_slow_timeout; /**< Time-out (in seconds) for slow advertising. */ -} ble_adv_modes_config_t; - -/**@brief BLE advertising event handler type. */ -typedef void (*ble_adv_evt_handler_t) (ble_adv_evt_t const adv_evt); - -/**@brief BLE advertising error handler type. */ -typedef void (*ble_adv_error_handler_t) (uint32_t nrf_error); - -typedef struct -{ - bool initialized; - bool advertising_start_pending; /**< Flag to keep track of ongoing operations in flash. */ - - ble_adv_evt_t adv_evt; /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address. */ - - ble_adv_mode_t adv_mode_current; /**< Variable to keep track of the current advertising mode. */ - ble_adv_modes_config_t adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/ - uint8_t conn_cfg_tag; /**< Variable to keep track of what connection settings will be used if the advertising results in a connection. */ - - ble_gap_addr_t peer_address; /**< Address of the most recently connected peer, used for direct advertising. */ - bool peer_addr_reply_expected; /**< Flag to verify that peer address is only set when requested. */ - - ble_advdata_t advdata; /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */ - ble_advdata_manuf_data_t manuf_specific_data; /**< Manufacturer specific data structure*/ - uint8_t manuf_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the Manufacturer specific data*/ - ble_advdata_service_data_t service_data; /**< Service data structure. */ - uint8_t service_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the service data. */ - ble_advdata_conn_int_t slave_conn_int; /**< Connection interval range structure.*/ - uint16_t current_slave_link_conn_handle; /**< Connection handle for the active link. */ - - ble_adv_evt_handler_t evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */ - ble_adv_error_handler_t error_handler; /**< Handler for the advertising error events. */ - - bool whitelist_temporarily_disabled; /**< Flag to keep track of temporary disabling of the whitelist. */ - bool whitelist_reply_expected; - -#if (NRF_SD_BLE_API_VERSION <= 2) - // For SoftDevices v 2.x, this module caches a whitelist which is retrieved from the - // application using an event, and which is passed as a parameter when calling - // sd_ble_gap_adv_start(). - ble_gap_addr_t * p_whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_irk_t * p_whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; - ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; - - ble_gap_whitelist_t m_whitelist = - { - .pp_addrs = p_whitelist_addrs, - .pp_irks = p_whitelist_irks - }; -#else - // For SoftDevices v 3.x, this module does not need to cache a whitelist, but it needs to - // be aware of whether or not a whitelist has been set (e.g. using the Peer Manager) - // in order to start advertising with the proper advertising params (filter policy). - bool whitelist_in_use; -#endif -} ble_advertising_t; - -typedef struct -{ - uint32_t interval; - uint32_t timeout; - bool enabled; -} ble_adv_mode_config_t; - -/**@brief Initialization parameters for the Advertising Module. - * @details This structure is used to pass advertising options, advertising data, - * and an event handler to the Advertising Module during initialization. - */ -typedef struct -{ - ble_advdata_t advdata; /**< Advertising data: name, appearance, discovery flags, and more. */ - ble_advdata_t srdata; /**< Scan response data: Supplement to advertising data. */ - ble_adv_modes_config_t config; /**< Select which advertising modes and intervals will be utilized.*/ - ble_adv_evt_handler_t evt_handler; /**< Event handler that will be called upon advertising events. */ - ble_adv_error_handler_t error_handler; /**< Error handler that will propogate internal errors to the main applications. */ -} ble_advertising_init_t; - - -/**@brief Function for handling BLE events. - * - * @details This function must be called from the BLE stack event dispatcher for - * the module to handle BLE events that are relevant for the Advertising Module. - * - * @param[in] p_ble_evt BLE stack event. - * @param[in] p_adv Advertising module instance. - */ -void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_adv); - - -/**@brief Function for handling system events. - * - * @details This function must be called to handle system events that are relevant - * for the Advertising Module. Specifically, the advertising module can not use the - * softdevice as long as there are pending writes to the flash memory. This - * event handler is designed to delay advertising until there is no flash operation. - * - * @param[in] sys_evt System event. - * @param[in] p_adv Advertising module instance. - */ -void ble_advertising_on_sys_evt(uint32_t sys_evt, void * p_adv); - - -/**@brief Function for initializing the Advertising Module. - * - * @details Encodes the required advertising data and passes it to the stack. - * Also builds a structure to be passed to the stack when starting advertising. - * The supplied advertising data is copied to a local structure and is manipulated - * depending on what advertising modes are started in @ref ble_advertising_start. - * - * @param[out] p_advertising Advertising module instance. This structure must be supplied by - * the application. It is initialized by this function and will later - * be used to identify this particular module instance. - * @param[in] p_init Information needed to initialize the module. - * - * @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned. - */ -uint32_t ble_advertising_init(ble_advertising_t * const p_advertising, - ble_advertising_init_t const * const p_init); - - - /**@brief Function for changing the connection settings tag that will be used for upcoming connections. - * - * @details See @ref sd_ble_cfg_set for more details about changing connection settings. If this - * function is never called, @ref BLE_CONN_CFG_TAG_DEFAULT will be used. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] ble_cfg_tag Configuration for the connection settings (see @ref sd_ble_cfg_set). - */ -void ble_advertising_conn_cfg_tag_set(ble_advertising_t * const p_advertising, uint8_t ble_cfg_tag); - -/**@brief Function for starting advertising. - * - * @details You can start advertising in any of the advertising modes that you enabled - * during initialization. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] advertising_mode Advertising mode. - * - * @retval @ref NRF_SUCCESS On success, else an error code indicating reason for failure. - * @retval @ref NRF_ERROR_INVALID_STATE If the module is not initialized. - */ -uint32_t ble_advertising_start(ble_advertising_t * const p_advertising, - ble_adv_mode_t advertising_mode); - - -/**@brief Function for setting the peer address. - * - * @details The peer address must be set by the application upon receiving a - * @ref BLE_ADV_EVT_PEER_ADDR_REQUEST event. Without the peer address, the directed - * advertising mode will not be run. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_peer_addr Pointer to a peer address. - * - * @retval @ref NRF_SUCCESS Successfully stored the peer address pointer in the advertising module. - * @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected. - */ -uint32_t ble_advertising_peer_addr_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t * p_peer_addr); - - -/**@brief Function for setting a whitelist. - * - * @details The whitelist must be set by the application upon receiving a - * @ref BLE_ADV_EVT_WHITELIST_REQUEST event. Without the whitelist, the whitelist - * advertising for fast and slow modes will not be run. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_gap_addrs The list of GAP addresses to whitelist. - * @param[in] addr_cnt The number of GAP addresses to whitelist. - * @param[in] p_gap_irks The list of peer IRK to whitelist. - * @param[in] irk_cnt The number of peer IRK to whitelist. - * - * @retval @ref NRF_SUCCESS If the operation was successful. - * @retval @ref NRF_ERROR_INVALID_STATE If a call to this function was made without a - * BLE_ADV_EVT_WHITELIST_REQUEST event being received. - */ -uint32_t ble_advertising_whitelist_reply(ble_advertising_t * const p_advertising, - ble_gap_addr_t const * p_gap_addrs, - uint32_t addr_cnt, - ble_gap_irk_t const * p_gap_irks, - uint32_t irk_cnt); - - -/**@brief Function for disabling whitelist advertising. - * - * @details This function temporarily disables whitelist advertising. - * Calling this function resets the current time-out countdown. - * - * @param[in] p_advertising Advertising module instance. - * - * @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice. - */ -uint32_t ble_advertising_restart_without_whitelist(ble_advertising_t * const p_advertising); - - -/**@brief Function for changing advertising modes configuration. - * - * @details This function can be called if you wish to reconfigure the advertising modes that the - * advertising module will cycle through. Enable or disable modes as listed in - * @ref ble_adv_mode_t; or change the duration of the advertising and use of whitelist. - * - * Keep in mind that @ref ble_adv_modes_config_t is also supplied when calling - * @ref ble_advertising_init. Calling @ref ble_advertising_modes_config_set - * is only necessary if your application requires this behaviour to change. - * - * @param[in] p_advertising Advertising module instance. - * @param[in] p_adv_modes_config Struct to keep track of disabled and enabled advertising modes, - * as well as time-outs and intervals. - */ -void ble_advertising_modes_config_set(ble_advertising_t * const p_advertising, - ble_adv_modes_config_t const * const p_adv_modes_config); -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_ADVERTISING_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c deleted file mode 100644 index d54d6ef773..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.c +++ /dev/null @@ -1,986 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "sdk_common.h" - -#if NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) -#include "ble_db_discovery.h" -#include -#include "ble_srv_common.h" -#define NRF_LOG_MODULE_NAME ble_db_disc -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - -#define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */ -#define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */ -#define MODULE_INITIALIZED (m_initialized == true) /**< Macro designating whether the module has been initialized properly. */ - - -/**@brief Array of structures containing information about the registered application modules. */ -static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS]; - - -/**@brief Array of structures containing pending events to be sent to the application modules. - * - * @details Whenever a discovery related event is to be raised to a user module, it will be stored - * in this array first. When all services needed to be discovered have been - * discovered, all pending events will be sent to the corresponding user modules. - **/ -static struct -{ - ble_db_discovery_evt_t evt; /**< The pending event. */ - ble_db_discovery_evt_handler_t evt_handler; /**< The event handler which should be called to raise this event. */ -} m_pending_user_evts[DB_DISCOVERY_MAX_USERS]; - -static ble_db_discovery_evt_handler_t m_evt_handler; -static uint32_t m_pending_usr_evt_index; /**< The index to the pending user event array, pointing to the last added pending user event. */ -static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */ -static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */ - -/**@brief Function for fetching the event handler provided by a registered application module. - * - * @param[in] srv_uuid UUID of the service. - * - * @retval evt_handler Event handler of the module, registered for the given service UUID. - * @retval NULL If no event handler is found. - */ -static ble_db_discovery_evt_handler_t registered_handler_get(ble_uuid_t const * p_srv_uuid) -{ - for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) - { - if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid)) - { - return (m_evt_handler); - } - } - - return NULL; -} - - -/**@brief Function for storing the event handler provided by a registered application module. - * - * @param[in] p_srv_uuid The UUID of the service. - * @param[in] p_evt_handler The event handler provided by the application. - * - * @retval NRF_SUCCESS If the handler was stored or already present in the list. - * @retval NRF_ERROR_NO_MEM If there is no space left to store the handler. - */ -static uint32_t registered_handler_set(ble_uuid_t const * p_srv_uuid, - ble_db_discovery_evt_handler_t p_evt_handler) -{ - if (registered_handler_get(p_srv_uuid) != NULL) - { - return NRF_SUCCESS; - } - - if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS) - { - m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid; - m_num_of_handlers_reg++; - - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_NO_MEM; - } -} - - -/**@brief Function for sending all pending discovery events to the corresponding user modules. - */ -static void pending_user_evts_send(void) -{ - for (uint32_t i = 0; i < m_num_of_handlers_reg; i++) - { - // Pass the event to the corresponding event handler. - m_pending_user_evts[i].evt_handler(&(m_pending_user_evts[i].evt)); - } - - m_pending_usr_evt_index = 0; -} - - -/**@brief Function for indicating error to the application. - * - * @details This function will fetch the event handler based on the UUID of the service being - * discovered. (The event handler is registered by the application beforehand). - * The error code is added to the pending events together with the event handler. - * If no event handler was found, then this function will do nothing. - * - * @param[in] p_db_discovery Pointer to the DB discovery structure. - * @param[in] err_code Error code that should be provided to the application. - * @param[in] conn_handle Connection Handle. - * - */ -static void discovery_error_evt_trigger(ble_db_discovery_t * p_db_discovery, - uint32_t err_code, - uint16_t conn_handle) -{ - ble_db_discovery_evt_handler_t p_evt_handler; - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); - - if (p_evt_handler != NULL) - { - ble_db_discovery_evt_t evt = - { - .conn_handle = conn_handle, - .evt_type = BLE_DB_DISCOVERY_ERROR, - .params.err_code = err_code, - }; - - p_evt_handler(&evt); - } -} - - -/**@brief Function for triggering a Discovery Complete or Service Not Found event to the - * application. - * - * @details This function will fetch the event handler based on the UUID of the service being - * discovered. (The event handler is registered by the application beforehand). - * It then triggers an event indicating the completion of the service discovery. - * If no event handler was found, then this function will do nothing. - * - * @param[in] p_db_discovery Pointer to the DB discovery structure. - * @param[in] is_srv_found Variable to indicate if the service was found at the peer. - * @param[in] conn_handle Connection Handle. - */ -static void discovery_complete_evt_trigger(ble_db_discovery_t * p_db_discovery, - bool is_srv_found, - uint16_t conn_handle) -{ - ble_db_discovery_evt_handler_t p_evt_handler; - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid)); - - if (p_evt_handler != NULL) - { - if (m_pending_usr_evt_index < DB_DISCOVERY_MAX_USERS) - { - // Insert an event into the pending event list. - m_pending_user_evts[m_pending_usr_evt_index].evt.conn_handle = conn_handle; - m_pending_user_evts[m_pending_usr_evt_index].evt.params.discovered_db = - *p_srv_being_discovered; - - if (is_srv_found) - { - m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type = - BLE_DB_DISCOVERY_COMPLETE; - } - else - { - m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type = - BLE_DB_DISCOVERY_SRV_NOT_FOUND; - } - - m_pending_user_evts[m_pending_usr_evt_index].evt_handler = p_evt_handler; - m_pending_usr_evt_index++; - - if (m_pending_usr_evt_index == m_num_of_handlers_reg) - { - // All registered modules have pending events. Send all pending events to the user - // modules. - pending_user_evts_send(); - } - else - { - // Too many events pending. Do nothing. (Ideally this should not happen.) - } - } - } -} - - -/**@brief Function for handling service discovery completion. - * - * @details This function will be used to determine if there are more services to be discovered, - * and if so, initiate the discovery of the next service. - * - * @param[in] p_db_discovery Pointer to the DB Discovery Structure. - * @param[in] conn_handle Connection Handle. - */ -static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle) -{ - p_db_discovery->discoveries_count++; - - // Check if more services need to be discovered. - if (p_db_discovery->discoveries_count < m_num_of_handlers_reg) - { - // Reset the current characteristic index since a new service discovery is about to start. - p_db_discovery->curr_char_ind = 0; - - // Initiate discovery of the next service. - p_db_discovery->curr_srv_ind++; - - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; - - // Reset the characteristic count in the current service to zero since a new service - // discovery is about to start. - p_srv_being_discovered->char_count = 0; - - NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, conn_handle); - - uint32_t err_code; - - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - SRV_DISC_START_HANDLE, - &(p_srv_being_discovered->srv_uuid)); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = conn_handle; - - return; - } - } - else - { - // No more service discovery is needed. - p_db_discovery->discovery_in_progress = false; - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = conn_handle; - } -} - - -/**@brief Function for finding out if a characteristic discovery should be performed after the - * last discovered characteristic. - * - * @details This function is used during the time of database discovery to find out if there is - * a need to do more characteristic discoveries. The value handles of the - * last discovered characteristic is compared with the end handle of the service. - * If the service handle is greater than one of the former characteristic handles, - * it means that a characteristic discovery is required. - * - * @param[in] p_db_discovery The pointer to the DB Discovery structure. - * @param[in] p_after_char The pointer to the last discovered characteristic. - * - * @retval True if a characteristic discovery is required. - * @retval False if a characteristic discovery is NOT required. - */ -static bool is_char_discovery_reqd(ble_db_discovery_t * p_db_discovery, - ble_gattc_char_t * p_after_char) -{ - if (p_after_char->handle_value < - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle) - { - // Handle value of the characteristic being discovered is less than the end handle of - // the service being discovered. There is a possibility of more characteristics being - // present. Hence a characteristic discovery is required. - return true; - } - - return false; -} - - -/**@brief Function to find out if a descriptor discovery is required. - * - * @details This function finds out if there is a possibility of existence of descriptors between - * current characteristic and the next characteristic. If so, this function will compute - * the handle range on which the descriptors may be present and will return it. - * If the current characteristic is the last known characteristic, then this function - * will use the service end handle to find out if the current characteristic can have - * descriptors. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_curr_char Pointer to the current characteristic. - * @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the - * caller knows that there is no characteristic after the current - * characteristic at the peer. - * @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the - * the peer. - * - * @retval True If a descriptor discovery is required. - * @retval False If a descriptor discovery is NOT required. - */ -static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery, - ble_gatt_db_char_t * p_curr_char, - ble_gatt_db_char_t * p_next_char, - ble_gattc_handle_range_t * p_handle_range) -{ - if (p_next_char == NULL) - { - // Current characteristic is the last characteristic in the service. Check if the value - // handle of the current characteristic is equal to the service end handle. - if ( - p_curr_char->characteristic.handle_value == - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle - ) - { - // No descriptors can be present for the current characteristic. p_curr_char is the last - // characteristic with no descriptors. - return false; - } - - p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; - - // Since the current characteristic is the last characteristic in the service, the end - // handle should be the end handle of the service. - p_handle_range->end_handle = - p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle; - - return true; - } - - // p_next_char != NULL. Check for existence of descriptors between the current and the next - // characteristic. - if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl) - { - // No descriptors can exist between the two characteristic. - return false; - } - - p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1; - p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1; - - return true; -} - - -/**@brief Function for performing characteristic discovery. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] conn_handle Connection Handle. - * - * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic - * discovery. Otherwise an error code. This function returns the error code returned - * by the SoftDevice API @ref sd_ble_gattc_characteristics_discover. - */ -static uint32_t characteristics_discover(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle) -{ - ble_gatt_db_srv_t * p_srv_being_discovered; - ble_gattc_handle_range_t handle_range; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_db_discovery->curr_char_ind != 0) - { - // This is not the first characteristic being discovered. Hence the 'start handle' to be - // used must be computed using the handle_value of the previous characteristic. - ble_gattc_char_t * p_prev_char; - uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic); - - handle_range.start_handle = p_prev_char->handle_value + 1; - } - else - { - // This is the first characteristic of this service being discovered. - handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle; - } - - handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle; - - return sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); -} - - -/**@brief Function for performing descriptor discovery, if required. - * - * @details This function will check if descriptor discovery is required and then perform it if - * needed. If no more descriptor discovery is required for the service, then the output - * parameter p_raise_discov_complete is set to true, indicating to the caller that a - * discovery complete event can be triggered to the application. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if - * the Discovery Complete event can be triggered to the - * application. - * @param[in] conn_handle Connection Handle. - * - * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor - * discovery, or if no more descriptor discovery is required. Otherwise an error code. - * This function returns the error code returned by the SoftDevice API @ref - * sd_ble_gattc_descriptors_discover. - */ -static uint32_t descriptors_discover(ble_db_discovery_t * p_db_discovery, - bool * p_raise_discov_complete, - uint16_t conn_handle) -{ - ble_gattc_handle_range_t handle_range; - ble_gatt_db_char_t * p_curr_char_being_discovered; - ble_gatt_db_srv_t * p_srv_being_discovered; - bool is_discovery_reqd = false; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_curr_char_being_discovered = - &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); - - if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) - { - // This is the last characteristic of this service. - is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery, - p_curr_char_being_discovered, - NULL, - &handle_range); - } - else - { - uint8_t i; - ble_gatt_db_char_t * p_next_char; - - for (i = p_db_discovery->curr_char_ind; i < p_srv_being_discovered->char_count; i++) - { - if (i == (p_srv_being_discovered->char_count - 1)) - { - // The current characteristic is the last characteristic in the service. - p_next_char = NULL; - } - else - { - p_next_char = &(p_srv_being_discovered->charateristics[i + 1]); - } - - // Check if it is possible for the current characteristic to have a descriptor. - if (is_desc_discovery_reqd(p_db_discovery, - p_curr_char_being_discovered, - p_next_char, - &handle_range)) - { - is_discovery_reqd = true; - break; - } - else - { - // No descriptors can exist. - p_curr_char_being_discovered = p_next_char; - p_db_discovery->curr_char_ind++; - } - } - } - - if (!is_discovery_reqd) - { - // No more descriptor discovery required. Discovery is complete. - // This informs the caller that a discovery complete event can be triggered. - *p_raise_discov_complete = true; - - return NRF_SUCCESS; - } - - *p_raise_discov_complete = false; - - return sd_ble_gattc_descriptors_discover(conn_handle, &handle_range); -} - - -/**@brief Function for handling primary service discovery response. - * - * @details This function will handle the primary service discovery response and start the - * discovery of characteristics within that service. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_primary_srv_discovery_rsp(ble_db_discovery_t * p_db_discovery, - ble_gattc_evt_t const * p_ble_gattc_evt) -{ - ble_gatt_db_srv_t * p_srv_being_discovered; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - uint32_t err_code; - ble_gattc_evt_prim_srvc_disc_rsp_t const * p_prim_srvc_disc_rsp_evt; - - NRF_LOG_DEBUG("Found service UUID 0x%x.", p_srv_being_discovered->srv_uuid.uuid); - - p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp); - - p_srv_being_discovered->srv_uuid = p_prim_srvc_disc_rsp_evt->services[0].uuid; - p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range; - - err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - } - } - else - { - NRF_LOG_DEBUG("Service UUID 0x%x not found.", p_srv_being_discovered->srv_uuid.uuid); - // Trigger Service Not Found event to the application. - discovery_complete_evt_trigger(p_db_discovery, false, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } -} - - -/**@brief Function for handling characteristic discovery response. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_characteristic_discovery_rsp(ble_db_discovery_t * p_db_discovery, - ble_gattc_evt_t const * p_ble_gattc_evt) -{ - uint32_t err_code; - ble_gatt_db_srv_t * p_srv_being_discovered; - bool perform_desc_discov = false; - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - ble_gattc_evt_char_disc_rsp_t const * p_char_disc_rsp_evt; - - p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp); - - // Find out the number of characteristics that were previously discovered (in earlier - // characteristic discovery responses, if any). - uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count; - - // Find out the number of characteristics that are currently discovered (in the - // characteristic discovery response being handled). - uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count; - - // Check if the total number of discovered characteristics are supported by this module. - if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS) - { - // Update the characteristics count. - p_srv_being_discovered->char_count += num_chars_curr_disc; - } - else - { - // The number of characteristics discovered at the peer is more than the supported - // maximum. This module will store only the characteristics found up to this point. - p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS; - } - - uint32_t i; - uint32_t j; - - for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++) - { - p_srv_being_discovered->charateristics[i].characteristic = - p_char_disc_rsp_evt->chars[j]; - - p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].ext_prop_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].user_desc_handle = BLE_GATT_HANDLE_INVALID; - p_srv_being_discovered->charateristics[i].report_ref_handle = BLE_GATT_HANDLE_INVALID; - } - - ble_gattc_char_t * p_last_known_char; - - p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic); - - // If no more characteristic discovery is required, or if the maximum number of supported - // characteristic per service has been reached, descriptor discovery will be performed. - if ( !is_char_discovery_reqd(p_db_discovery, p_last_known_char) - || (p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS)) - { - perform_desc_discov = true; - } - else - { - // Update the current characteristic index. - p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count; - - // Perform another round of characteristic discovery. - err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - } - } - else - { - // The previous characteristic discovery resulted in no characteristics. - // descriptor discovery should be performed. - perform_desc_discov = true; - } - - if (perform_desc_discov) - { - bool raise_discov_complete; - - p_db_discovery->curr_char_ind = 0; - - err_code = descriptors_discover(p_db_discovery, - &raise_discov_complete, - p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - if (raise_discov_complete) - { - // No more characteristics and descriptors need to be discovered. Discovery is complete. - // Send a discovery complete event to the user application. - NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" - " on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, - p_ble_gattc_evt->conn_handle); - - discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } - } -} - - -/**@brief Function for handling descriptor discovery response. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GATT Client event. - */ -static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery, - const ble_gattc_evt_t * const p_ble_gattc_evt) -{ - const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt; - ble_gatt_db_srv_t * p_srv_being_discovered; - - if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle) - { - return; - } - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - - p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp); - - ble_gatt_db_char_t * p_char_being_discovered = - &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]); - - if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS) - { - // The descriptor was found at the peer. - // Iterate through and collect CCCD, Extended Properties, - // User Description & Report Reference descriptor handles. - for (uint32_t i = 0; i < p_desc_disc_rsp_evt->count; i++) - { - switch (p_desc_disc_rsp_evt->descs[i].uuid.uuid) - { - case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: - p_char_being_discovered->cccd_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP: - p_char_being_discovered->ext_prop_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: - p_char_being_discovered->user_desc_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - - case BLE_UUID_REPORT_REF_DESCR: - p_char_being_discovered->report_ref_handle = - p_desc_disc_rsp_evt->descs[i].handle; - break; - } - - /* Break if we've found all the descriptors we are looking for. */ - if (p_char_being_discovered->cccd_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->ext_prop_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->user_desc_handle != BLE_GATT_HANDLE_INVALID && - p_char_being_discovered->report_ref_handle != BLE_GATT_HANDLE_INVALID) - { - break; - } - } - } - - bool raise_discov_complete = false; - - if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count) - { - // No more characteristics and descriptors need to be discovered. Discovery is complete. - // Send a discovery complete event to the user application. - - raise_discov_complete = true; - } - else - { - // Begin discovery of descriptors for the next characteristic. - uint32_t err_code; - - p_db_discovery->curr_char_ind++; - - err_code = descriptors_discover(p_db_discovery, - &raise_discov_complete, - p_ble_gattc_evt->conn_handle); - - if (err_code != NRF_SUCCESS) - { - p_db_discovery->discovery_in_progress = false; - - // Error with discovering the service. - // Indicate the error to the registered user application. - discovery_error_evt_trigger(p_db_discovery, err_code, p_ble_gattc_evt->conn_handle); - - m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE; - m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle; - - return; - } - } - - if (raise_discov_complete) - { - NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success" - " on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, - p_ble_gattc_evt->conn_handle); - - discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle); - on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle); - } -} - - -uint32_t ble_db_discovery_init(const ble_db_discovery_evt_handler_t evt_handler) -{ - uint32_t err_code = NRF_SUCCESS; - VERIFY_PARAM_NOT_NULL(evt_handler); - - m_num_of_handlers_reg = 0; - m_initialized = true; - m_pending_usr_evt_index = 0; - m_evt_handler = evt_handler; - - return err_code; - -} - - -uint32_t ble_db_discovery_close() -{ - m_num_of_handlers_reg = 0; - m_initialized = false; - m_pending_usr_evt_index = 0; - - return NRF_SUCCESS; -} - - -uint32_t ble_db_discovery_evt_register(ble_uuid_t const * p_uuid) -{ - VERIFY_PARAM_NOT_NULL(p_uuid); - VERIFY_MODULE_INITIALIZED(); - - return registered_handler_set(p_uuid, m_evt_handler); -} - - -static uint32_t discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) -{ - uint32_t err_code; - ble_gatt_db_srv_t * p_srv_being_discovered; - - memset(p_db_discovery, 0x00, sizeof(ble_db_discovery_t)); - - p_db_discovery->conn_handle = conn_handle; - - m_pending_usr_evt_index = 0; - - p_db_discovery->discoveries_count = 0; - p_db_discovery->curr_srv_ind = 0; - p_db_discovery->curr_char_ind = 0; - - p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]); - p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind]; - - NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.", - p_srv_being_discovered->srv_uuid.uuid, conn_handle); - - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - SRV_DISC_START_HANDLE, - &(p_srv_being_discovered->srv_uuid)); - if (err_code != NRF_ERROR_BUSY) - { - VERIFY_SUCCESS(err_code); - p_db_discovery->discovery_in_progress = true; - p_db_discovery->discovery_pending = false; - } - else - { - p_db_discovery->discovery_in_progress = true; - p_db_discovery->discovery_pending = true; - } - - return NRF_SUCCESS; -} - - -uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle) -{ - VERIFY_PARAM_NOT_NULL(p_db_discovery); - VERIFY_MODULE_INITIALIZED(); - - if (m_num_of_handlers_reg == 0) - { - // No user modules were registered. There are no services to discover. - return NRF_ERROR_INVALID_STATE; - } - - if (p_db_discovery->discovery_in_progress) - { - return NRF_ERROR_BUSY; - } - - return discovery_start(p_db_discovery, conn_handle); -} - - -/**@brief Function for handling disconnected event. - * - * @param[in] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] p_ble_gattc_evt Pointer to the GAP event. - */ -static void on_disconnected(ble_db_discovery_t * p_db_discovery, - ble_gap_evt_t const * p_evt) -{ - if (p_evt->conn_handle == p_db_discovery->conn_handle) - { - p_db_discovery->discovery_in_progress = false; - p_db_discovery->discovery_pending = false; - p_db_discovery->conn_handle = BLE_CONN_HANDLE_INVALID; - } -} - - -void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, - void * p_context) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); - VERIFY_PARAM_NOT_NULL_VOID(p_context); - VERIFY_MODULE_INITIALIZED_VOID(); - - ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GATTC_EVT_DESC_DISC_RSP: - on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt)); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt)); - break; - - default: - break; - } - - if ( (p_db_discovery->discovery_pending) - && (p_ble_evt->header.evt_id >= BLE_GATTC_EVT_BASE) - && (p_ble_evt->header.evt_id <= BLE_GATTC_EVT_LAST) - && (p_ble_evt->evt.gattc_evt.conn_handle == p_db_discovery->conn_handle)) - { - (void)discovery_start(p_db_discovery, p_db_discovery->conn_handle); - } -} -#endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h deleted file mode 100644 index e1fe1f554e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_db_discovery/ble_db_discovery.h +++ /dev/null @@ -1,235 +0,0 @@ -/** - * Copyright (c) 2013 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_db_discovery Database Discovery - * @{ - * @ingroup ble_sdk_lib - * @brief Database discovery module. - * - * @details This module contains the APIs and types exposed by the DB Discovery module. These APIs - * and types can be used by the application to perform discovery of a service and its - * characteristics at the peer server. This module can also be used to discover the - * desired services in multiple remote devices. - * - * @warning The maximum number of characteristics per service that can be discovered by this module - * is determined by the number of characteristics in the service structure defined in - * db_disc_config.h. If the peer has more than the supported number of characteristics, then - * the first found will be discovered and any further characteristics will be ignored. Only the - * following descriptors will be searched for at the peer: Client Characteristic Configuration, - * Characteristic Extended Properties, Characteristic User Description, and Report Reference. - * - * @note Presently only one instance of a Primary Service can be discovered by this module. If - * there are multiple instances of the service at the peer, only the first instance - * of it at the peer is fetched and returned to the application. - * - * @note The application must propagate BLE stack events to this module by calling - * ble_db_discovery_on_ble_evt(). - * - */ - -#ifndef BLE_DB_DISCOVERY_H__ -#define BLE_DB_DISCOVERY_H__ - -#include -#include -#include "nrf_error.h" -#include "nrf_ble.h" -#include "ble_gattc.h" -#include "ble_gatt_db.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a ble_db_discovery instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define BLE_DB_DISCOVERY_DEF(_name) \ -static ble_db_discovery_t _name = {.discovery_in_progress = 0, \ - .discovery_pending = 0, \ - .conn_handle = BLE_CONN_HANDLE_INVALID}; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - BLE_DB_DISC_BLE_OBSERVER_PRIO, \ - ble_db_discovery_on_ble_evt, &_name) - -/** @brief Macro for defining multiple ble_db_discovery instances. - * - * @param _name Name of the array of instances. - * @param _cnt Number of instances to define. - */ -#define BLE_DB_DISCOVERY_ARRAY_DEF(_name, _cnt) \ -static ble_db_discovery_t _name[_cnt] = {{.discovery_in_progress = 0, \ - .discovery_pending = 0, \ - .conn_handle = BLE_CONN_HANDLE_INVALID}}; \ -NRF_SDH_BLE_OBSERVERS(_name ## _obs, \ - BLE_DB_DISC_BLE_OBSERVER_PRIO, \ - ble_db_discovery_on_ble_evt, &_name, _cnt) - -#define BLE_DB_DISCOVERY_MAX_SRV 6 /**< Maximum number of services supported by this module. This also indicates the maximum number of users allowed to be registered to this module (one user per service). */ - - -/**@brief DB Discovery event type. */ -typedef enum -{ - BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the discovery of one service is complete. */ - BLE_DB_DISCOVERY_ERROR, /**< Event indicating that an internal error has occurred in the DB Discovery module. This could typically be because of the SoftDevice API returning an error code during the DB discover.*/ - BLE_DB_DISCOVERY_SRV_NOT_FOUND, /**< Event indicating that the service was not found at the peer.*/ - BLE_DB_DISCOVERY_AVAILABLE /**< Event indicating that the DB discovery instance is available.*/ -} ble_db_discovery_evt_type_t; - -/**@brief Structure for holding the information related to the GATT database at the server. - * - * @details This module identifies a remote database. Use one instance of this structure per - * connection. - * - * @warning This structure must be zero-initialized. - */ -typedef struct -{ - ble_gatt_db_srv_t services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. This is intended for internal use during service discovery.*/ - uint8_t srv_count; /**< Number of services at the peers GATT database.*/ - uint8_t curr_char_ind; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/ - uint8_t curr_srv_ind; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/ - bool discovery_in_progress; /**< Variable to indicate if there is a service discovery in progress. */ - bool discovery_pending; /**< Discovery was requested, but could not start because the SoftDevice was busy. */ - uint8_t discoveries_count; /**< Number of service discoveries made, both successful and unsuccessful. */ - uint16_t conn_handle; /**< Connection handle on which the discovery is started*/ -} ble_db_discovery_t; - -/**@brief Structure containing the event from the DB discovery module to the application. */ -typedef struct -{ - ble_db_discovery_evt_type_t evt_type; /**< Type of event. */ - uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */ - union - { - ble_gatt_db_srv_t discovered_db; /**< Structure containing the information about the GATT Database at the server. This will be filled when the event type is @ref BLE_DB_DISCOVERY_COMPLETE. The UUID field of this will be filled when the event type is @ref BLE_DB_DISCOVERY_SRV_NOT_FOUND. */ - uint32_t err_code; /**< nRF Error code indicating the type of error which occurred in the DB Discovery module. This will be filled when the event type is @ref BLE_DB_DISCOVERY_ERROR. */ - } params; -} ble_db_discovery_evt_t; - -/**@brief DB Discovery event handler type. */ -typedef void (* ble_db_discovery_evt_handler_t)(ble_db_discovery_evt_t * p_evt); - - -/**@brief Function for initializing the DB Discovery module. - * - * @param[in] evt_handler Event handler to be called by the DB discovery module when any event - * related to discovery of the registered service occurs. - * - * @retval NRF_SUCCESS On successful initialization. - * @retval NRF_ERROR_NULL If the handler was NULL. - */ -uint32_t ble_db_discovery_init(ble_db_discovery_evt_handler_t evt_handler); - - -/**@brief Function for closing the DB Discovery module. - * - * @details This function will clear up any internal variables and states maintained by the - * module. To re-use the module after calling this function, the function @ref - * ble_db_discovery_init must be called again. - * - * @retval NRF_SUCCESS Operation success. - */ -uint32_t ble_db_discovery_close(void); - - -/**@brief Function for registering with the DB Discovery module. - * - * @details The application can use this function to inform which service it is interested in - * discovering at the server. - * - * @param[in] p_uuid Pointer to the UUID of the service to be discovered at the server. - * - * @note The total number of services that can be discovered by this module is @ref - * BLE_DB_DISCOVERY_MAX_SRV. This effectively means that the maximum number of - * registrations possible is equal to the @ref BLE_DB_DISCOVERY_MAX_SRV. - * - * @retval NRF_SUCCESS Operation success. - * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. - * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the - * @ref ble_db_discovery_init. - * @retval NRF_ERROR_NO_MEM The maximum number of registrations allowed by this module - * has been reached. - */ -uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid); - - -/**@brief Function for starting the discovery of the GATT database at the server. - * - * @param[out] p_db_discovery Pointer to the DB Discovery structure. - * @param[in] conn_handle The handle of the connection for which the discovery should be - * started. - * - * @retval NRF_SUCCESS Operation success. - * @retval NRF_ERROR_NULL When a NULL pointer is passed as input. - * @retval NRF_ERROR_INVALID_STATE If this function is called without calling the - * @ref ble_db_discovery_init, or without calling - * @ref ble_db_discovery_evt_register. - * @retval NRF_ERROR_BUSY If a discovery is already in progress using - * @p p_db_discovery. Use a different @ref ble_db_discovery_t - * structure, or wait for a DB Discovery event before retrying. - * - * @return This API propagates the error code returned by the - * SoftDevice API @ref sd_ble_gattc_primary_services_discover. - */ -uint32_t ble_db_discovery_start(ble_db_discovery_t * p_db_discovery, - uint16_t conn_handle); - - -/**@brief Function for handling the Application's BLE Stack events. - * - * @param[in] p_ble_evt Pointer to the BLE event received. - * @param[in,out] p_context Pointer to the DB Discovery structure. - */ -void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt, - void * p_context); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DB_DISCOVERY_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c deleted file mode 100644 index 3aa8f1c587..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.c +++ /dev/null @@ -1,942 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_DTM) -#include "ble_dtm.h" -#include "ble_dtm_hw.h" -#include -#include -#include "nrf.h" - -#define DTM_HEADER_OFFSET 0 /**< Index where the header of the pdu is located. */ -#define DTM_HEADER_SIZE 2 /**< Size of PDU header. */ -#define DTM_PAYLOAD_MAX_SIZE 255 /**< Maximum payload size allowed during dtm execution. */ -#define DTM_LENGTH_OFFSET (DTM_HEADER_OFFSET + 1) /**< Index where the length of the payload is encoded. */ -#define DTM_PDU_MAX_MEMORY_SIZE (DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE) /**< Maximum PDU size allowed during dtm execution. */ -#define DTM_ON_AIR_OVERHEAD_SIZE 10 /**< Size of the packet on air without the payload (preamble + sync word + type + RFU + length + CRC). */ - -#define RX_MODE true /**< Constant defining RX mode for radio during dtm test. */ -#define TX_MODE false /**< Constant defining TX mode for radio during dtm test. */ - -#define PHYS_CH_MAX 39 /**< Maximum number of valid channels in BLE. */ - -// Values that for now are "constants" - they could be configured by a function setting them, -// but most of these are set by the BLE DTM standard, so changing them is not relevant. -#define RFPHY_TEST_0X0F_REF_PATTERN 0x0f /**< RF-PHY test packet patterns, for the repeated octet packets. */ -#define RFPHY_TEST_0X55_REF_PATTERN 0x55 /**< RF-PHY test packet patterns, for the repeated octet packets. */ -#define RFPHY_TEST_0XFF_REF_PATTERN 0xFF /**< RF-PHY test packet patterns, for the repeated octet packets. */ - -#define PRBS9_CONTENT {0xFF, 0xC1, 0xFB, 0xE8, 0x4C, 0x90, 0x72, 0x8B, \ - 0xE7, 0xB3, 0x51, 0x89, 0x63, 0xAB, 0x23, 0x23, \ - 0x02, 0x84, 0x18, 0x72, 0xAA, 0x61, 0x2F, 0x3B, \ - 0x51, 0xA8, 0xE5, 0x37, 0x49, 0xFB, 0xC9, 0xCA, \ - 0x0C, 0x18, 0x53, 0x2C, 0xFD, 0x45, 0xE3, 0x9A, \ - 0xE6, 0xF1, 0x5D, 0xB0, 0xB6, 0x1B, 0xB4, 0xBE, \ - 0x2A, 0x50, 0xEA, 0xE9, 0x0E, 0x9C, 0x4B, 0x5E, \ - 0x57, 0x24, 0xCC, 0xA1, 0xB7, 0x59, 0xB8, 0x87, \ - 0xFF, 0xE0, 0x7D, 0x74, 0x26, 0x48, 0xB9, 0xC5, \ - 0xF3, 0xD9, 0xA8, 0xC4, 0xB1, 0xD5, 0x91, 0x11, \ - 0x01, 0x42, 0x0C, 0x39, 0xD5, 0xB0, 0x97, 0x9D, \ - 0x28, 0xD4, 0xF2, 0x9B, 0xA4, 0xFD, 0x64, 0x65, \ - 0x06, 0x8C, 0x29, 0x96, 0xFE, 0xA2, 0x71, 0x4D, \ - 0xF3, 0xF8, 0x2E, 0x58, 0xDB, 0x0D, 0x5A, 0x5F, \ - 0x15, 0x28, 0xF5, 0x74, 0x07, 0xCE, 0x25, 0xAF, \ - 0x2B, 0x12, 0xE6, 0xD0, 0xDB, 0x2C, 0xDC, 0xC3, \ - 0x7F, 0xF0, 0x3E, 0x3A, 0x13, 0xA4, 0xDC, 0xE2, \ - 0xF9, 0x6C, 0x54, 0xE2, 0xD8, 0xEA, 0xC8, 0x88, \ - 0x00, 0x21, 0x86, 0x9C, 0x6A, 0xD8, 0xCB, 0x4E, \ - 0x14, 0x6A, 0xF9, 0x4D, 0xD2, 0x7E, 0xB2, 0x32, \ - 0x03, 0xC6, 0x14, 0x4B, 0x7F, 0xD1, 0xB8, 0xA6, \ - 0x79, 0x7C, 0x17, 0xAC, 0xED, 0x06, 0xAD, 0xAF, \ - 0x0A, 0x94, 0x7A, 0xBA, 0x03, 0xE7, 0x92, 0xD7, \ - 0x15, 0x09, 0x73, 0xE8, 0x6D, 0x16, 0xEE, 0xE1, \ - 0x3F, 0x78, 0x1F, 0x9D, 0x09, 0x52, 0x6E, 0xF1, \ - 0x7C, 0x36, 0x2A, 0x71, 0x6C, 0x75, 0x64, 0x44, \ - 0x80, 0x10, 0x43, 0x4E, 0x35, 0xEC, 0x65, 0x27, \ - 0x0A, 0xB5, 0xFC, 0x26, 0x69, 0x3F, 0x59, 0x99, \ - 0x01, 0x63, 0x8A, 0xA5, 0xBF, 0x68, 0x5C, 0xD3, \ - 0x3C, 0xBE, 0x0B, 0xD6, 0x76, 0x83, 0xD6, 0x57, \ - 0x05, 0x4A, 0x3D, 0xDD, 0x81, 0x73, 0xC9, 0xEB, \ - 0x8A, 0x84, 0x39, 0xF4, 0x36, 0x0B, 0xF7} /**< The PRBS9 sequence used as packet payload. - The bytes in the sequence is in the right order, but the bits of each byte in the array is reverse. - of that found by running the PRBS9 algorithm. This is because of the endianess of the nRF5 radio. */ - -/**@brief Structure holding the PDU used for transmitting/receiving a PDU. - */ -typedef struct -{ - uint8_t content[DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE]; /**< PDU packet content. */ -} pdu_type_t; - -/**@brief States used for the DTM test implementation. - */ -typedef enum -{ - STATE_UNINITIALIZED, /**< The DTM is uninitialized. */ - STATE_IDLE, /**< State when system has just initialized, or current test has completed. */ - STATE_TRANSMITTER_TEST, /**< State used when a DTM Transmission test is running. */ - STATE_CARRIER_TEST, /**< State used when a DTM Carrier test is running (Vendor specific test). */ - STATE_RECEIVER_TEST /**< State used when a DTM Receive test is running. */ -} state_t; - - -// Internal variables set as side effects of commands or events. -static state_t m_state = STATE_UNINITIALIZED; /**< Current machine state. */ -static uint16_t m_rx_pkt_count; /**< Number of valid packets received. */ -static pdu_type_t m_pdu; /**< PDU to be sent. */ -static uint16_t m_event; /**< current command status - initially "ok", may be set if error detected, or to packet count. */ -static bool m_new_event; /**< Command has been processed - number of not yet reported event bytes. */ -static uint32_t m_packet_length; /**< Payload length of transmitted PDU, bits 2:7 of 16-bit dtm command. */ -static dtm_pkt_type_t m_packet_type; /**< Bits 0..1 of 16-bit transmit command, or 0xFFFFFFFF. */ -static dtm_freq_t m_phys_ch; /**< 0..39 physical channel number (base 2402 MHz, Interval 2 MHz), bits 8:13 of 16-bit dtm command. */ -static uint32_t m_current_time = 0; /**< Counter for interrupts from timer to ensure that the 2 bytes forming a DTM command are received within the time window. */ - -// Nordic specific configuration values (not defined by BLE standard). -// Definition of initial values found in ble_dtm.h -static int32_t m_tx_power = DEFAULT_TX_POWER; /**< TX power for transmission test, default to maximum value (+4 dBm). */ -static NRF_TIMER_Type * mp_timer = DEFAULT_TIMER; /**< Timer to be used. */ -static IRQn_Type m_timer_irq = DEFAULT_TIMER_IRQn; /**< which interrupt line to clear on every timeout */ - -static uint8_t const m_prbs_content[] = PRBS9_CONTENT; /**< Pseudo-random bit sequence defined by the BLE standard. */ -static uint8_t m_packetHeaderLFlen = 8; /**< Length of length field in packet Header (in bits). */ -static uint8_t m_packetHeaderS0len = 1; /**< Length of S0 field in packet Header (in bytes). */ -static uint8_t m_packetHeaderS1len = 0; /**< Length of S1 field in packet Header (in bits). */ -static uint8_t m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; /**< Length of the preamble. */ - -static uint8_t m_crcConfSkipAddr = 1; /**< Leave packet address field out of CRC calculation. */ -static uint8_t m_static_length = 0; /**< Number of bytes sent in addition to the var.length payload. */ -static uint32_t m_balen = 3; /**< Base address length in bytes. */ -static uint32_t m_endian = RADIO_PCNF1_ENDIAN_Little; /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */ -static uint32_t m_whitening = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */ -static uint8_t m_crcLength = RADIO_CRCCNF_LEN_Three; /**< CRC Length (in bytes). */ -static uint32_t m_address = 0x71764129; /**< Address. */ -static uint32_t m_crc_poly = 0x0000065B; /**< CRC polynomial. */ -static uint32_t m_crc_init = 0x00555555; /**< Initial value for CRC calculation. */ -static uint8_t m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; /**< nRF51 specific radio mode value. */ -static uint32_t m_txIntervaluS = 2500; /**< Time between start of Tx packets (in uS). */ - - -/**@brief Function for verifying that a received PDU has the expected structure and content. - */ -static bool check_pdu(void) -{ - uint8_t k; // Byte pointer for running through PDU payload - uint8_t pattern; // Repeating octet value in payload - dtm_pkt_type_t pdu_packet_type; // Note: PDU packet type is a 4-bit field in HCI, but 2 bits in BLE DTM - uint32_t length = 0; - - pdu_packet_type = (dtm_pkt_type_t)(m_pdu.content[DTM_HEADER_OFFSET] & 0x0F); - length = m_pdu.content[DTM_LENGTH_OFFSET]; - - // Check that the length is valid. - if (length > DTM_PAYLOAD_MAX_SIZE) - { - return false; - } - - // If the 1Mbit or 2Mbit radio mode is active, check that one of the three valid uncoded DTM packet types are selected. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0X55)) - { - return false; - } - -#ifdef NRF52840_XXAA - // If a long range radio mode is active, check that one of the four valid coded DTM packet types are selected. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit) && (pdu_packet_type > (dtm_pkt_type_t)DTM_PKT_0XFF)) - { - return false; - } -#endif - - if (pdu_packet_type == DTM_PKT_PRBS9) - { - // Payload does not consist of one repeated octet; must compare ir with entire block into - return (memcmp(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, length) == 0); - } - - if (pdu_packet_type == DTM_PKT_0X0F) - { - pattern = RFPHY_TEST_0X0F_REF_PATTERN; - } - else if (pdu_packet_type == DTM_PKT_0X55) - { - pattern = RFPHY_TEST_0X55_REF_PATTERN; - } - else if (pdu_packet_type == DTM_PKT_0XFF) - { - pattern = RFPHY_TEST_0XFF_REF_PATTERN; - } - else - { - // No valid packet type set. - return false; - } - - for (k = 0; k < length; k++) - { - // Check repeated pattern filling the PDU payload - if (m_pdu.content[k + 2] != pattern) - { - return false; - } - } - return true; -} - - -/**@brief Function for turning off the radio after a test. - * Also called after test done, to be ready for next test. - */ -static void radio_reset(void) -{ - NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk | PPI_CHENCLR_CH1_Msk; - - NRF_RADIO->SHORTS = 0; - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->TASKS_DISABLE = 1; - - while (NRF_RADIO->EVENTS_DISABLED == 0) - { - // Do nothing - } - - NRF_RADIO->EVENTS_DISABLED = 0; - NRF_RADIO->TASKS_RXEN = 0; - NRF_RADIO->TASKS_TXEN = 0; - - m_rx_pkt_count = 0; -} - - -/**@brief Function for initializing the radio for DTM. - */ -static uint32_t radio_init(void) -{ - if (dtm_radio_validate(m_tx_power, m_radio_mode) != DTM_SUCCESS) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - // Turn off radio before configuring it - radio_reset(); - - NRF_RADIO->TXPOWER = m_tx_power; - NRF_RADIO->MODE = m_radio_mode << RADIO_MODE_MODE_Pos; - - // Set the access address, address0/prefix0 used for both Rx and Tx address - NRF_RADIO->PREFIX0 &= ~RADIO_PREFIX0_AP0_Msk; - NRF_RADIO->PREFIX0 |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk; - NRF_RADIO->BASE0 = m_address << 8; - NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos; - NRF_RADIO->TXADDRESS = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk; - - // Configure CRC calculation - NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) | - (m_crcLength << RADIO_CRCCNF_LEN_Pos); - - if (m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) - { - // Non-coded PHY - NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | - (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | - (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | - (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); - } -#ifdef NRF52840_XXAA - else - { - // Coded PHY (Long range) - NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) | - (m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) | - (m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos) | - (3 << RADIO_PCNF0_TERMLEN_Pos) | - (2 << RADIO_PCNF0_CILEN_Pos) | - (m_packetHeaderPlen << RADIO_PCNF0_PLEN_Pos); - } -#endif - - NRF_RADIO->PCNF1 = (m_whitening << RADIO_PCNF1_WHITEEN_Pos) | - (m_endian << RADIO_PCNF1_ENDIAN_Pos) | - (m_balen << RADIO_PCNF1_BALEN_Pos) | - (m_static_length << RADIO_PCNF1_STATLEN_Pos) | - (DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos); - - return DTM_SUCCESS; -} - - -/**@brief Function for preparing the radio. At start of each test: Turn off RF, clear interrupt flags of RF, initialize the radio - * at given RF channel. - * - *@param[in] rx boolean indicating if radio should be prepared in rx mode (true) or tx mode. - */ -static void radio_prepare(bool rx) -{ - dtm_turn_off_test(); - NRF_RADIO->CRCPOLY = m_crc_poly; - NRF_RADIO->CRCINIT = m_crc_init; - NRF_RADIO->FREQUENCY = (m_phys_ch << 1) + 2; // Actual frequency (MHz): 2400 + register value - NRF_RADIO->PACKETPTR = (uint32_t)&m_pdu; // Setting packet pointer will start the radio - NRF_RADIO->EVENTS_READY = 0; - NRF_RADIO->SHORTS = (1 << RADIO_SHORTS_READY_START_Pos) | // Shortcut between READY event and START task - (1 << RADIO_SHORTS_END_DISABLE_Pos); // Shortcut between END event and DISABLE task - - if (rx) - { - NRF_RADIO->EVENTS_END = 0; - NRF_RADIO->TASKS_RXEN = 1; // shorts will start radio in RX mode when it is ready - } - else // tx - { - NRF_RADIO->TXPOWER = m_tx_power; - } -} - - -/**@brief Function for terminating the ongoing test (if any) and closing down the radio. - */ -static void dtm_test_done(void) -{ - dtm_turn_off_test(); - NRF_PPI->CHENCLR = 0x01; - NRF_PPI->CH[0].EEP = 0; // Break connection from timer to radio to stop transmit loop - NRF_PPI->CH[0].TEP = 0; - - radio_reset(); - m_state = STATE_IDLE; -} - - -/**@brief Function for configuring the timer for 625us cycle time. - */ -static uint32_t timer_init(void) -{ - // Use 16MHz from external crystal - // This could be customized for RC/Xtal, or even to use a 32 kHz crystal - NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; - NRF_CLOCK->TASKS_HFCLKSTART = 1; - - while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) - { - // Do nothing while waiting for the clock to start - } - - mp_timer->TASKS_STOP = 1; // Stop timer, if it was running - mp_timer->TASKS_CLEAR = 1; - mp_timer->MODE = TIMER_MODE_MODE_Timer; // Timer mode (not counter) - mp_timer->EVENTS_COMPARE[0] = 0; // clean up possible old events - mp_timer->EVENTS_COMPARE[1] = 0; - mp_timer->EVENTS_COMPARE[2] = 0; - mp_timer->EVENTS_COMPARE[3] = 0; - - // Timer is polled, but enable the compare0 interrupt in order to wakeup from CPU sleep - mp_timer->INTENSET = TIMER_INTENSET_COMPARE0_Msk; - mp_timer->SHORTS = 1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos; // Clear the count every time timer reaches the CCREG0 count - mp_timer->PRESCALER = 4; // Input clock is 16MHz, timer clock = 2 ^ prescale -> interval 1us - mp_timer->CC[0] = m_txIntervaluS; // 625uS with 1MHz clock to the timer - mp_timer->CC[1] = UART_POLL_CYCLE; // Depends on the baud rate of the UART. Default baud rate of 19200 will result in a 260uS time with 1MHz clock to the timer - mp_timer->TASKS_START = 1; // Start the timer - it will be running continuously - m_current_time = 0; - return DTM_SUCCESS; -} - - -/**@brief Function for handling vendor specific commands. - * Used when packet type is set to Vendor specific. - * The length field is used for encoding vendor specific command. - * The frequency field is used for encoding vendor specific options to the command. - * - * @param[in] vendor_cmd Vendor specific command to be executed. - * @param[in] vendor_option Vendor specific option to the vendor command. - * - * @return DTM_SUCCESS or one of the DTM_ERROR_ values - */ -static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd, dtm_freq_t vendor_option) -{ - switch (vendor_cmd) - { - // nRFgo Studio uses CARRIER_TEST_STUDIO to indicate a continuous carrier without - // a modulated signal. - case CARRIER_TEST: - case CARRIER_TEST_STUDIO: - // Not a packet type, but used to indicate that a continuous carrier signal - // should be transmitted by the radio. - radio_prepare(TX_MODE); - - dtm_constant_carrier(); - - // Shortcut between READY event and START task - NRF_RADIO->SHORTS = 1 << RADIO_SHORTS_READY_START_Pos; - - // Shortcut will start radio in Tx mode when it is ready - NRF_RADIO->TASKS_TXEN = 1; - m_state = STATE_CARRIER_TEST; - break; - - case SET_TX_POWER: - if (!dtm_set_txpower(vendor_option)) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - break; - - case SELECT_TIMER: - if (!dtm_set_timer(vendor_option)) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - break; - } - // Event code is unchanged, successful - return DTM_SUCCESS; -} - - -static uint32_t dtm_packet_interval_calculate(uint32_t test_payload_length, uint32_t mode) -{ - uint32_t test_packet_length = 0; // [us] NOTE: bits are us at 1Mbit - uint32_t packet_interval = 0; // us - uint32_t overhead_bits = 0; // bits - - /* packet overhead - * see BLE [Vol 6, Part F] page 213 - * 4.1 LE TEST PACKET FORMAT */ - if (mode == RADIO_MODE_MODE_Ble_2Mbit) - { - // 16 preamble - // 32 sync word - // 8 PDU header, actually packetHeaderS0len * 8 - // 8 PDU length, actually packetHeaderLFlen - // 24 CRC - overhead_bits = 88; // 11 bytes - } - else if (mode == RADIO_MODE_MODE_Ble_1Mbit) - { - // 8 preamble - // 32 sync word - // 8 PDU header, actually packetHeaderS0len * 8 - // 8 PDU length, actually packetHeaderLFlen - // 24 CRC - overhead_bits = 80; // 10 bytes - } -#ifdef NRF52840_XXAA - else if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) - { - // 80 preamble - // 32 * 8 sync word coding=8 - // 2 * 8 Coding indicator, coding=8 - // 3 * 8 TERM1 coding=8 - // 8 * 8 PDU header, actually packetHeaderS0len * 8 coding=8 - // 8 * 8 PDU length, actually packetHeaderLFlen coding=8 - // 24 * 8 CRC coding=8 - // 3 * 8 TERM2 coding=8 - overhead_bits = 720; // 90 bytes - } - else if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) - { - // 80 preamble - // 32 * 8 sync word coding=8 - // 2 * 8 Coding indicator, coding=8 - // 3 * 8 TERM 1 coding=8 - // 8 * 2 PDU header, actually packetHeaderS0len * 8 coding=2 - // 8 * 2 PDU length, actually packetHeaderLFlen coding=2 - // 24 * 2 CRC coding=2 - // 3 * 2 TERM2 coding=2 - // NOTE: this makes us clock out 46 bits for CI + TERM1 + TERM2 - // assumption the radio will handle this - overhead_bits = 462; // 57.75 bytes - } -#endif - /* add PDU payload test_payload length */ - test_packet_length = (test_payload_length * 8); // in bits -#ifdef NRF52840_XXAA - // account for the encoding of PDU - if (mode == RADIO_MODE_MODE_Ble_LR125Kbit) - { - test_packet_length *= 8; // 1 to 8 encoding - } - if (mode == RADIO_MODE_MODE_Ble_LR500Kbit) - { - test_packet_length *= 2; // 1 to 2 encoding - } -#endif - // add overhead calculated above - test_packet_length += overhead_bits; - // we remember this bits are us in 1Mbit - if (mode == RADIO_MODE_MODE_Ble_2Mbit) - { - test_packet_length /= 2; // double speed - } - - /* - * packet_interval = ceil((test_packet_length+249)/625)*625 - * NOTE: To avoid floating point an equivalent calculation is used. - */ - uint32_t i = 0; - uint32_t timeout = 0; - do - { - i++; - timeout = i * 625; - } while (test_packet_length + 249 > timeout); - packet_interval = i * 625; - - return packet_interval; -} - - -uint32_t dtm_init(void) -{ - if ((timer_init() != DTM_SUCCESS) || (radio_init() != DTM_SUCCESS)) - { - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - m_new_event = false; - m_state = STATE_IDLE; - m_packet_length = 0; - - // Enable wake-up on event - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - - return DTM_SUCCESS; -} - - -uint32_t dtm_wait(void) -{ - // Enable wake-up on event - SCB->SCR |= SCB_SCR_SEVONPEND_Msk; - - for (;;) - { - // Event may be the reception of a packet - - // handle radio first, to give it highest priority: - if (NRF_RADIO->EVENTS_END != 0) - { - NRF_RADIO->EVENTS_END = 0; - NVIC_ClearPendingIRQ(RADIO_IRQn); - - if (m_state == STATE_RECEIVER_TEST) - { - NRF_RADIO->TASKS_RXEN = 1; - if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu()) - { - // Count the number of successfully received packets - m_rx_pkt_count++; - } - // Note that failing packets are simply ignored (CRC or contents error). - - // Zero fill all pdu fields to avoid stray data - memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); - } - // If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!) - } - - // Check for timeouts: - if (mp_timer->EVENTS_COMPARE[0] != 0) - { - mp_timer->EVENTS_COMPARE[0] = 0; - } - else if (mp_timer->EVENTS_COMPARE[1] != 0) - { - // Reset timeout event flag for next iteration. - mp_timer->EVENTS_COMPARE[1] = 0; - NVIC_ClearPendingIRQ(m_timer_irq); - return ++m_current_time; - } - - // Other events: No processing - } -} - -uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload) -{ - // Save specified packet in static variable for tx/rx functions to use. - // Note that BLE conformance testers always use full length packets. - m_packet_length = (m_packet_length & 0xC0) | ((uint8_t)length & 0x3F); - m_packet_type = payload; - m_phys_ch = freq; - - // If 1 Mbit or 2 Mbit radio mode is in use check for Vendor Specific payload. - if ((m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit) && payload == DTM_PKT_VENDORSPECIFIC) - { - /* Note that in a HCI adaption layer, as well as in the DTM PDU format, - the value 0x03 is a distinct bit pattern (PRBS15). Even though BLE does not - support PRBS15, this implementation re-maps 0x03 to DTM_PKT_VENDORSPECIFIC, - to avoid the risk of confusion, should the code be extended to greater coverage. - */ - m_packet_type = DTM_PKT_TYPE_VENDORSPECIFIC; - } - - // Clean out any non-retrieved event that might linger from an earlier test - m_new_event = true; - - // Set default event; any error will set it to LE_TEST_STATUS_EVENT_ERROR - m_event = LE_TEST_STATUS_EVENT_SUCCESS; - - if (m_state == STATE_UNINITIALIZED) - { - // Application has not explicitly initialized DTM, - return DTM_ERROR_UNINITIALIZED; - } - - if (cmd == LE_TEST_SETUP) - { - // Note that timer will continue running after a reset - dtm_test_done(); - if (freq == LE_TEST_SETUP_RESET) - { - if (length != 0x00) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // Reset the packet length upper bits. - m_packet_length = 0; - - // Reset the selected PHY to 1Mbit - m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - } - else if (freq == LE_TEST_SETUP_SET_UPPER) - { - if (length > 0x03) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - m_packet_length = length << 6; - } - else if (freq == LE_TEST_SETUP_SET_PHY) - { - switch (length) - { - case LE_PHY_1M: - m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_8bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - - return radio_init(); - - case LE_PHY_2M: - m_radio_mode = RADIO_MODE_MODE_Ble_2Mbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_16bit; - -#ifdef NRF52840_XXAA - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif - - return radio_init(); - - case LE_PHY_LE_CODED_S8: -#ifdef NRF52840_XXAA - m_radio_mode = RADIO_MODE_MODE_Ble_LR125Kbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; - - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); - - return radio_init(); -#else - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; -#endif // NRF52840_XXAA - case LE_PHY_LE_CODED_S2: -#ifdef NRF52840_XXAA - m_radio_mode = RADIO_MODE_MODE_Ble_LR500Kbit; - m_packetHeaderPlen = RADIO_PCNF0_PLEN_LongRange; - - // Workaround for Errata ID 164 - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); - - return radio_init(); -#else - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; -#endif - default: - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - } - else if(freq == LE_TEST_SETUP_SELECT_MODULATION) - { - if (length > 0x01) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // Only standard modulation is supported. - } - else if (freq == LE_TEST_SETUP_READ_SUPPORTED) - { - if (length != 0x00) - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - // 0XXXXXXXXXXX0110 indicate that 2Mbit and DLE is supported and stable modulation is not supported (No nRF5 device supports this). - m_event = 0x0006; - } - else if (freq == LE_TEST_SETUP_READ_MAX) - { - // Read max supported value. - switch (length) - { - case 0x00: - // Read supportedMaxTxOctets - m_event = 0x01FE; - break; - - case 0x01: - // Read supportedMaxTxTime - m_event = 0x4290; - break; - - case 0x02: - // Read supportedMaxRxOctets - m_event = 0x01FE; - break; - - case 0x03: - // Read supportedMaxRxTime - m_event = 0x4290; - break; - - default: - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - } - else - { - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - return DTM_SUCCESS; - } - - if (cmd == LE_TEST_END) - { - if (m_state == STATE_IDLE) - { - // Sequencing error - only rx or tx test may be ended! - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_INVALID_STATE; - } - m_event = LE_PACKET_REPORTING_EVENT | m_rx_pkt_count; - dtm_test_done(); - return DTM_SUCCESS; - } - - if (m_state != STATE_IDLE) - { - // Sequencing error - only TEST_END/RESET are legal while test is running - // Note: State is unchanged; ongoing test not affected - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_INVALID_STATE; - } - - // Check for illegal values of m_phys_ch. Skip the check if the packet is vendor spesific. - if (payload != DTM_PKT_VENDORSPECIFIC && m_phys_ch > PHYS_CH_MAX) - { - // Parameter error - // Note: State is unchanged; ongoing test not affected - m_event = LE_TEST_STATUS_EVENT_ERROR; - - return DTM_ERROR_ILLEGAL_CHANNEL; - } - - m_rx_pkt_count = 0; - - if (cmd == LE_RECEIVER_TEST) - { - // Zero fill all pdu fields to avoid stray data from earlier test run - memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE); - radio_prepare(RX_MODE); // Reinitialize "everything"; RF interrupts OFF - m_state = STATE_RECEIVER_TEST; - return DTM_SUCCESS; - } - - if (cmd == LE_TRANSMITTER_TEST) - { - // Check for illegal values of m_packet_length. Skip the check if the packet is vendor spesific. - if (m_packet_type != DTM_PKT_TYPE_VENDORSPECIFIC && m_packet_length > DTM_PAYLOAD_MAX_SIZE) - { - // Parameter error - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_LENGTH; - } - - - m_pdu.content[DTM_LENGTH_OFFSET] = m_packet_length; - // Note that PDU uses 4 bits even though BLE DTM uses only 2 (the HCI SDU uses all 4) - switch (m_packet_type) - { - case DTM_PKT_PRBS9: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_PRBS9; - // Non-repeated, must copy entire pattern to PDU - memcpy(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, m_packet_length); - break; - - case DTM_PKT_0X0F: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X0F; - // Bit pattern 00001111 repeated - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X0F_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_0X55: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0X55; - // Bit pattern 01010101 repeated - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X55_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_0XFF: - m_pdu.content[DTM_HEADER_OFFSET] = DTM_PDU_TYPE_0XFF; - // Bit pattern 11111111 repeated. Only available in coded PHY (Long range). - memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0XFF_REF_PATTERN, m_packet_length); - break; - - case DTM_PKT_TYPE_VENDORSPECIFIC: - // The length field is for indicating the vendor specific command to execute. - // The frequency field is used for vendor specific options to the command. - return dtm_vendor_specific_pkt(length, freq); - - default: - // Parameter error - m_event = LE_TEST_STATUS_EVENT_ERROR; - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - // Initialize CRC value, set channel: - radio_prepare(TX_MODE); - - // Set the timer to the correct period. The delay between each packet is described in the - // Bluetooth Core Spsification version 4.2 Vol. 6 Part F Section 4.1.6. - mp_timer->CC[0] = dtm_packet_interval_calculate(m_packet_length, m_radio_mode); - - // Configure PPI so that timer will activate radio every 625 us - NRF_PPI->CH[0].EEP = (uint32_t)&mp_timer->EVENTS_COMPARE[0]; - NRF_PPI->CH[0].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN; - NRF_PPI->CHENSET = 0x01; - m_state = STATE_TRANSMITTER_TEST; - } - return DTM_SUCCESS; -} - - -bool dtm_event_get(dtm_event_t *p_dtm_event) -{ - bool was_new = m_new_event; - // mark the current event as retrieved - m_new_event = false; - *p_dtm_event = m_event; - // return value indicates whether this value was already retrieved. - return was_new; -} - - -// ================================================================================================= -// Configuration functions (only for parameters not definitely determined by the BLE DTM standard). -// These functions return true if successful, false if value could not be set - - -/**@brief Function for configuring the output power for transmitter test. - This function may be called directly, or through dtm_cmd() specifying - DTM_PKT_VENDORSPECIFIC as payload, SET_TX_POWER as length, and the dBm value as frequency. - */ -bool dtm_set_txpower(uint32_t new_tx_power) -{ - // radio->TXPOWER register is 32 bits, low octet a signed value, upper 24 bits zeroed - int8_t new_power8 = (int8_t)(new_tx_power & 0xFF); - - // The two most significant bits are not sent in the 6 bit field of the DTM command. - // These two bits are 1's if and only if the tx_power is a negative number. - // All valid negative values have the fourth most significant bit as 1. - // All valid positive values have the fourth most significant bit as 0. - // By checking this bit, the two most significant bits can be determined. - new_power8 = (new_power8 & 0x30) != 0 ? (new_power8 | 0xC0) : new_power8; - - if (m_state > STATE_IDLE) - { - // radio must be idle to change the tx power - return false; - } - - m_tx_power = new_power8; - - return true; -} - - -/**@brief Function for selecting a timer resource. - * This function may be called directly, or through dtm_cmd() specifying - * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq - * - * @param[in] new_timer Timer id for the timer to use: 0, 1, or 2. - * - * @return true if the timer was successfully changed, false otherwise. - */ -bool dtm_set_timer(uint32_t new_timer) -{ - if (m_state > STATE_IDLE) - { - return false; - } - return dtm_hw_set_timer(&mp_timer, &m_timer_irq, new_timer); -} - -/// @} -#endif // NRF_MODULE_ENABLED(BLE_DTM) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h deleted file mode 100644 index 04066cbc2e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm.h +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_dtm DTM - Direct Test Mode - * @{ - * @ingroup ble_sdk_lib - * @brief Module for testing RF/PHY using DTM commands. - */ - -#ifndef BLE_DTM_H__ -#define BLE_DTM_H__ - -#include -#include -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Configuration parameters. */ -#define DTM_BITRATE UARTE_BAUDRATE_BAUDRATE_Baud19200 /**< Serial bitrate on the UART */ -#define DEFAULT_TX_POWER RADIO_TXPOWER_TXPOWER_0dBm /**< Default Transmission power using in the DTM module. */ -#define DEFAULT_TIMER NRF_TIMER0 /**< Default timer used for timing. */ -#define DEFAULT_TIMER_IRQn TIMER0_IRQn /**< IRQ used for timer. NOTE: MUST correspond to DEFAULT_TIMER. */ - -/**@brief BLE DTM command codes. */ -typedef uint32_t dtm_cmd_t; /**< DTM command type. */ - -#define LE_TEST_SETUP 0 /**< DTM command: Set PHY or modulation, configure upper two bits of length, - request matrix of supported features or request max values of parameters. */ -#define LE_RECEIVER_TEST 1 /**< DTM command: Start receive test. */ -#define LE_TRANSMITTER_TEST 2 /**< DTM command: Start transmission test. */ -#define LE_TEST_END 3 /**< DTM command: End test and send packet report. */ - -#define LE_TEST_SETUP_RESET 0 /**< DTM command parameter: Stop TX/RX, reset the packet length upper bits and set the PHY to 1Mbit. */ -#define LE_TEST_SETUP_SET_UPPER 1 /**< DTM command parameter: Set the upper two bits of the length field. */ -#define LE_TEST_SETUP_SET_PHY 2 /**< DTM command parameter: Select the PHY to be used for packets. */ -#define LE_TEST_SETUP_SELECT_MODULATION 3 /**< DTM command parameter: Select standard or stable modulation index. Stable modulation index is not supported. */ -#define LE_TEST_SETUP_READ_SUPPORTED 4 /**< DTM command parameter: Read the supported test case features. */ -#define LE_TEST_SETUP_READ_MAX 5 /**< DTM command parameter: Read the max supported time and length for packets. */ - -#define LE_PHY_1M 1 /**< DTM command parameter: Set PHY for future packets to use 1MBit PHY. */ -#define LE_PHY_2M 2 /**< DTM command parameter: Set PHY for future packets to use 2MBit PHY. */ -#define LE_PHY_LE_CODED_S8 3 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=8. */ -#define LE_PHY_LE_CODED_S2 4 /**< DTM command parameter: Set PHY for future packets to use coded PHY with S=2 */ - -// Configuration options used as parameter 2 -// when cmd == LE_TRANSMITTER_TEST and payload == DTM_PKT_VENDORSPECIFIC -// Configuration value, if any, is supplied in parameter 3 - -#define CARRIER_TEST 0 /**< Length=0 indicates a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ -#define CARRIER_TEST_STUDIO 1 /**< nRFgo Studio uses value 1 in length field, to indicate a constant, unmodulated carrier until LE_TEST_END or LE_RESET */ -#define SET_TX_POWER 2 /**< Set transmission power, value -40..+4 dBm in steps of 4 */ -#define SELECT_TIMER 3 /**< Select on of the 16 MHz timers 0, 1 or 2 */ - -#define LE_PACKET_REPORTING_EVENT 0x8000 /**< DTM Packet reporting event, returned by the device to the tester. */ -#define LE_TEST_STATUS_EVENT_SUCCESS 0x0000 /**< DTM Status event, indicating success. */ -#define LE_TEST_STATUS_EVENT_ERROR 0x0001 /**< DTM Status event, indicating an error. */ - -#define DTM_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */ -#define DTM_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */ -#define DTM_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */ -#define DTM_PKT_0XFF 0x03 /**< Bit pattern 11111111 (Used only for coded PHY). */ -#define DTM_PKT_VENDORSPECIFIC 0x03 /**< Vendor specific PKT field value. Nordic: Continuous carrier test, or configuration. */ -#define DTM_PKT_TYPE_VENDORSPECIFIC 0xFF /**< Vendor specific packet type for internal use. */ - -// The pdu payload type for each bit pattern. Identical to the PKT value except pattern 0xFF which is 0x04. -#define DTM_PDU_TYPE_PRBS9 0x00 /**< PDU payload type for bit pattern PRBS9. */ -#define DTM_PDU_TYPE_0X0F 0x01 /**< PDU payload type for bit pattern 11110000 (LSB is the leftmost bit). */ -#define DTM_PDU_TYPE_0X55 0x02 /**< PDU payload type for bit pattern 10101010 (LSB is the leftmost bit). */ -#define DTM_PDU_TYPE_0XFF 0x04 /**< PDU payload type for bit pattern 11111111 (Used only for coded PHY). */ - -/**@brief Return codes from dtm_cmd(). */ -#define DTM_SUCCESS 0x00 /**< Indicate that the DTM function completed with success. */ -#define DTM_ERROR_ILLEGAL_CHANNEL 0x01 /**< Physical channel number must be in the range 0..39. */ -#define DTM_ERROR_INVALID_STATE 0x02 /**< Sequencing error: Command is not valid now. */ -#define DTM_ERROR_ILLEGAL_LENGTH 0x03 /**< Payload size must be in the range 0..37. */ -#define DTM_ERROR_ILLEGAL_CONFIGURATION 0x04 /**< Parameter out of range (legal range is function dependent). */ -#define DTM_ERROR_UNINITIALIZED 0x05 /**< DTM module has not been initialized by the application. */ - -/**@details The UART poll cycle in micro seconds. - * A baud rate of e.g. 19200 bits / second, and 8 data bits, 1 start/stop bit, no flow control, - * give the time to transmit a byte: 10 bits * 1/19200 = approx: 520 us. - * To ensure no loss of bytes, the UART should be polled every 260 us. - */ -#if DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud9600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/9600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud14400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/14400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud19200 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/19200/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud28800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/28800/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud38400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/38400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud57600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/57600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud76800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/768000/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud115200 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/115200/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud230400 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/230400/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud250000 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/250000/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud460800 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/460800/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud921600 -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/921600/2)) -#elif DTM_BITRATE == UARTE_BAUDRATE_BAUDRATE_Baud1M -#define UART_POLL_CYCLE ((uint32_t)(10*1e6/1e6/2)) -#else -// It is possible to find values that work for other baud rates, but the formula above is not -// guaranteed to work for all values. Suitable values may have to be found by trial and error. -#error "Unsupported baud rate set." -#endif - -// Note: DTM_PKT_VENDORSPECIFIC, is not a packet type -#define PACKET_TYPE_MAX DTM_PKT_0XFF /**< Highest value allowed as DTM Packet type. */ - -/** @brief BLE DTM event type. */ -typedef uint32_t dtm_event_t; /**< Type for handling DTM event. */ - -/** @brief BLE DTM frequency type. */ -typedef uint32_t dtm_freq_t; /**< Physical channel, valid range: 0..39. */ - -/**@brief BLE DTM packet types. */ -typedef uint32_t dtm_pkt_type_t; /**< Type for holding the requested DTM payload type.*/ - - -/**@brief Function for initializing or re-initializing DTM module - * - * @return DTM_SUCCESS on successful initialization of the DTM module. -*/ -uint32_t dtm_init(void); - - -/**@brief Function for giving control to dtmlib for handling timer and radio events. - * Will return to caller at 625us intervals or whenever another event than radio occurs - * (such as UART input). Function will put MCU to sleep between events. - * - * @return Time counter, incremented every 625 us. - */ -uint32_t dtm_wait(void); - - -/**@brief Function for calling when a complete command has been prepared by the Tester. - * - * @param[in] cmd One of the DTM_CMD values (bits 14:15 in the 16-bit UART format). - * @param[in] freq Phys. channel no - actual frequency = (2402 + freq * 2) MHz (bits 8:13 in - * the 16-bit UART format). - * @param[in] length Payload length, 0..37 (bits 2:7 in the 16-bit UART format). - * @param[in] payload One of the DTM_PKT values (bits 0:1 in the 16-bit UART format). - * - * @return DTM_SUCCESS or one of the DTM_ERROR_ values - */ -uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload); - - -/**@brief Function for reading the result of a DTM command - * - * @param[out] p_dtm_event Pointer to buffer for 16 bit event code according to DTM standard. - * - * @return true: new event, false: no event since last call, this event has been read earlier - */ -bool dtm_event_get(dtm_event_t * p_dtm_event); - - -/**@brief Function for configuring the timer to use. - * - * @note Must be called when no DTM test is running. - * - * @param[in] new_timer Index (0..2) of timer to be used by the DTM library - * - * @return true: success, new timer was selected, false: parameter error - */ -bool dtm_set_timer(uint32_t new_timer); - - -/**@brief Function for configuring the transmit power. - * - * @note Must be called when no DTM test is running. - * - * @param[in] new_tx_power New output level, +4..-40, in steps of 4. - * - * @return true: tx power setting changed, false: parameter error - */ -bool dtm_set_txpower(uint32_t new_tx_power); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DTM_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h deleted file mode 100644 index c63d155cc8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_dtm_hw Direct Test Mode HW - * @{ - * @ingroup ble_sdk_lib - * @brief Module contains hardware related function for testing RF/PHY using DTM commands. - */ - -#ifndef BLE_DTM_HW_H__ -#define BLE_DTM_HW_H__ - -#include -#include -#include "nrf.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Function for selecting a timer resource. - * This function may be called directly, or through dtm_cmd() specifying - * DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq - * - * @param[out] mp_timer Pointer to timer instance used in dtm source file. - * @param[out] m_timer_irq Pointer to timer interrupt related to mp_timer. - * @param[in] new_timer Timer id for the timer to use. - * - * @retval true if the timer was successfully changed. - * @retval false if the error occurs. - */ - -bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer); - - -/**@brief Function for turning off radio test. - * This function is platform depending. For now only nRF51 requieres this special function. - */ -void dtm_turn_off_test(void); - - -/**@brief Function for setting constant carrier in radio settings. - * This function is used to handle vendor specific command testing continous carrier without - * a modulated signal. - */ -void dtm_constant_carrier(void); - - -/**@brief Function for validating tx power and radio move settings. - * @param[in] m_tx_power TX power for transmission test. - * @param[in] m_radio_mode Radio mode value. - * - * @retval DTM_SUCCESS if input parameters values are correct. - * @retval DTM_ERROR_ILLEGAL_CONFIGURATION if input parameters values are not correct. - */ -uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode); - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DTM_HW_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c deleted file mode 100644 index 9f5f4b4d34..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_dtm/ble_dtm_hw_nrf52.c +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "ble_dtm_hw.h" -#include "ble_dtm.h" -#include -#include -#include "nrf.h" - - -void dtm_turn_off_test() -{ -} - - -void dtm_constant_carrier() -{ -NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) | - (RADIO_MODECNF0_DTX_Center << RADIO_MODECNF0_DTX_Pos); -} - - -uint32_t dtm_radio_validate(int32_t m_tx_power, uint8_t m_radio_mode) -{ - // Initializing code below is quite generic - for BLE, the values are fixed, and expressions - // are constant. Non-constant values are essentially set in radio_prepare(). - if (!(m_tx_power == RADIO_TXPOWER_TXPOWER_0dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Pos4dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg30dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg20dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg16dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg12dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg8dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg4dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Pos3dBm || - m_tx_power == RADIO_TXPOWER_TXPOWER_Neg40dBm - ) || - - !( -#ifdef NRF52840_XXAA - m_radio_mode == RADIO_MODE_MODE_Ble_LR125Kbit || - m_radio_mode == RADIO_MODE_MODE_Ble_LR500Kbit || -#endif //NRF52840_XXAA - m_radio_mode == RADIO_MODE_MODE_Ble_1Mbit || - m_radio_mode == RADIO_MODE_MODE_Ble_2Mbit - ) - ) - { - return DTM_ERROR_ILLEGAL_CONFIGURATION; - } - - return DTM_SUCCESS; -} - - -bool dtm_hw_set_timer(NRF_TIMER_Type ** mp_timer, IRQn_Type * m_timer_irq, uint32_t new_timer) -{ - if (new_timer == 0) - { - *mp_timer = NRF_TIMER0; - *m_timer_irq = TIMER0_IRQn; - } - else if (new_timer == 1) - { - *mp_timer = NRF_TIMER1; - *m_timer_irq = TIMER1_IRQn; - } - else if (new_timer == 2) - { - *mp_timer = NRF_TIMER2; - *m_timer_irq = TIMER2_IRQn; - } -#ifndef NRF52810_XXAA - else if (new_timer == 3) - { - *mp_timer = NRF_TIMER3; - *m_timer_irq = TIMER3_IRQn; - } - else if (new_timer == 4) - { - *mp_timer = NRF_TIMER4; - *m_timer_irq = TIMER4_IRQn; - } -#endif //NRF52810_XXAA - else - { - // Parameter error: Only TIMER 0, 1, 2, 3 and 4 provided by nRF52 - return false; - } - // New timer has been selected: - return true; -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c deleted file mode 100644 index 41a4ccb4f6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.c +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(BLE_RACP) -#include "ble_racp.h" -#include - - -void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val) -{ - p_racp_val->opcode = 0xFF; - p_racp_val->operator = 0xFF; - p_racp_val->operand_len = 0; - p_racp_val->p_operand = NULL; - - if (data_len > 0) - { - p_racp_val->opcode = p_data[0]; - } - if (data_len > 1) - { - p_racp_val->operator = p_data[1]; //lint !e415 - } - if (data_len > 2) - { - p_racp_val->operand_len = data_len - 2; - p_racp_val->p_operand = (uint8_t*)&p_data[2]; //lint !e416 - } -} - - -uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data) -{ - uint8_t len = 0; - int i; - - if (p_data != NULL) - { - p_data[len++] = p_racp_val->opcode; - p_data[len++] = p_racp_val->operator; - - for (i = 0; i < p_racp_val->operand_len; i++) - { - p_data[len++] = p_racp_val->p_operand[i]; - } - } - - return len; -} -#endif // NRF_MODULE_ENABLED(BLE_RACP) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h deleted file mode 100644 index 14da8b281b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/ble_racp/ble_racp.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_racp Record Access Control Point - * @{ - * @ingroup ble_sdk_lib - * @brief Record Access Control Point library. - */ - -#ifndef BLE_RACP_H__ -#define BLE_RACP_H__ - -#include -#include -#include "nrf_ble.h" -#include "ble_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Record Access Control Point opcodes. */ -#define RACP_OPCODE_RESERVED 0 /**< Record Access Control Point opcode - Reserved for future use. */ -#define RACP_OPCODE_REPORT_RECS 1 /**< Record Access Control Point opcode - Report stored records. */ -#define RACP_OPCODE_DELETE_RECS 2 /**< Record Access Control Point opcode - Delete stored records. */ -#define RACP_OPCODE_ABORT_OPERATION 3 /**< Record Access Control Point opcode - Abort operation. */ -#define RACP_OPCODE_REPORT_NUM_RECS 4 /**< Record Access Control Point opcode - Report number of stored records. */ -#define RACP_OPCODE_NUM_RECS_RESPONSE 5 /**< Record Access Control Point opcode - Number of stored records response. */ -#define RACP_OPCODE_RESPONSE_CODE 6 /**< Record Access Control Point opcode - Response code. */ - -/**@brief Record Access Control Point operators. */ -#define RACP_OPERATOR_NULL 0 /**< Record Access Control Point operator - Null. */ -#define RACP_OPERATOR_ALL 1 /**< Record Access Control Point operator - All records. */ -#define RACP_OPERATOR_LESS_OR_EQUAL 2 /**< Record Access Control Point operator - Less than or equal to. */ -#define RACP_OPERATOR_GREATER_OR_EQUAL 3 /**< Record Access Control Point operator - Greater than or equal to. */ -#define RACP_OPERATOR_RANGE 4 /**< Record Access Control Point operator - Within range of (inclusive). */ -#define RACP_OPERATOR_FIRST 5 /**< Record Access Control Point operator - First record (i.e. oldest record). */ -#define RACP_OPERATOR_LAST 6 /**< Record Access Control Point operator - Last record (i.e. most recent record). */ -#define RACP_OPERATOR_RFU_START 7 /**< Record Access Control Point operator - Start of Reserved for Future Use area. */ - -/**@brief Record Access Control Point Operand Filter Type Value. */ -#define RACP_OPERAND_FILTER_TYPE_TIME_OFFSET 1 /**< Record Access Control Point Operand Filter Type Value - Time Offset- */ - -/**@brief Record Access Control Point response codes. */ -#define RACP_RESPONSE_RESERVED 0 /**< Record Access Control Point response code - Reserved for future use. */ -#define RACP_RESPONSE_SUCCESS 1 /**< Record Access Control Point response code - Successful operation. */ -#define RACP_RESPONSE_OPCODE_UNSUPPORTED 2 /**< Record Access Control Point response code - Unsupported op code received. */ -#define RACP_RESPONSE_INVALID_OPERATOR 3 /**< Record Access Control Point response code - Operator not valid for service. */ -#define RACP_RESPONSE_OPERATOR_UNSUPPORTED 4 /**< Record Access Control Point response code - Unsupported operator. */ -#define RACP_RESPONSE_INVALID_OPERAND 5 /**< Record Access Control Point response code - Operand not valid for service. */ -#define RACP_RESPONSE_NO_RECORDS_FOUND 6 /**< Record Access Control Point response code - No matching records found. */ -#define RACP_RESPONSE_ABORT_FAILED 7 /**< Record Access Control Point response code - Abort could not be completed. */ -#define RACP_RESPONSE_PROCEDURE_NOT_DONE 8 /**< Record Access Control Point response code - Procedure could not be completed. */ -#define RACP_RESPONSE_OPERAND_UNSUPPORTED 9 /**< Record Access Control Point response code - Unsupported operand. */ - -/**@brief Record Access Control Point value structure. */ -typedef struct -{ - uint8_t opcode; /**< Op Code. */ - uint8_t operator; /**< Operator. */ - uint8_t operand_len; /**< Length of the operand. */ - uint8_t * p_operand; /**< Pointer to the operand. */ -} ble_racp_value_t; - -/**@brief Function for decoding a Record Access Control Point write. - * - * @details This call decodes a write to the Record Access Control Point. - * - * @param[in] data_len Length of data in received write. - * @param[in] p_data Pointer to received data. - * @param[out] p_racp_val Pointer to decoded Record Access Control Point write. - * @note This does not do a data copy. It assumes the data pointed to by - * p_data is persistant until no longer needed. - */ -void ble_racp_decode(uint8_t data_len, uint8_t const * p_data, ble_racp_value_t * p_racp_val); - -/**@brief Function for encoding a Record Access Control Point response. - * - * @details This call encodes a response from the Record Access Control Point response. - * - * @param[in] p_racp_val Pointer to Record Access Control Point to encode. - * @param[out] p_data Pointer to where encoded data is written. - * NOTE! It is calling routines respsonsibility to make sure. - * - * @return Length of encoded data. - */ -uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_RACP_H__ - -/** @} */ - diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c deleted file mode 100644 index dd0c43c97f..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.c +++ /dev/null @@ -1,706 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "ble_advdata.h" -#include "ble_gap.h" -#include "ble_srv_common.h" -#include "sdk_common.h" - -// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. - -#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ -#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ -#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ - -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ - AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ -#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ -#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ -#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ -#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ - -// Types of LE Bluetooth Device Address AD type -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL - -static uint32_t ble_device_addr_encode(uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - ble_gap_addr_t device_addr; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Get BLE address. - #if (NRF_SD_BLE_API_VERSION >= 3) - err_code = sd_ble_gap_addr_get(&device_addr); - #else - err_code = sd_ble_gap_address_get(&device_addr); - #endif - VERIFY_SUCCESS(err_code); - - // Encode LE Bluetooth Device Address. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; - *p_offset += AD_TYPE_FIELD_SIZE; - memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); - *p_offset += BLE_GAP_ADDR_LEN; - if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) - { - p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; - } - else - { - p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; - } - *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; - - return NRF_SUCCESS; -} - -static uint32_t name_encode(const ble_advdata_t * p_advdata, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - uint16_t rem_adv_data_len; - uint16_t actual_length; - uint8_t adv_data_format; - - - // Validate parameters - if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Check for buffer overflow. - if ( (((*p_offset) + AD_DATA_OFFSET) > max_size) || - ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && - (((*p_offset) + AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) - { - return NRF_ERROR_DATA_SIZE; - } - - rem_adv_data_len = max_size - (*p_offset) - AD_DATA_OFFSET; - actual_length = rem_adv_data_len; - - // Get GAP device name and length - err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + AD_DATA_OFFSET], - &actual_length); - VERIFY_SUCCESS(err_code); - - // Check if device intend to use short name and it can fit available data size. - if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len)) - { - // Complete device name can fit, setting Complete Name in Adv Data. - adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; - } - else - { - // Else short name needs to be used. Or application has requested use of short name. - adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; - - // If application has set a preference on the short name size, it needs to be considered, - // else fit what can be fit. - if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && - (p_advdata->short_name_len <= rem_adv_data_len)) - { - // Short name fits available size. - actual_length = p_advdata->short_name_len; - } - // Else whatever can fit the data buffer will be packed. - else - { - actual_length = rem_adv_data_len; - } - } - - // There is only 1 byte intended to encode length which is (actual_length + AD_TYPE_FIELD_SIZE) - if (actual_length > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Complete name field in encoded data. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + actual_length); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = adv_data_format; - *p_offset += AD_TYPE_FIELD_SIZE; - *p_offset += actual_length; - - return NRF_SUCCESS; -} - - -static uint32_t appearance_encode(uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - uint16_t appearance; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Get GAP appearance field. - err_code = sd_ble_gap_appearance_get(&appearance); - VERIFY_SUCCESS(err_code); - - // Encode Length, AD Type and Appearance. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; - *p_offset += AD_TYPE_FIELD_SIZE; - *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); - - return NRF_SUCCESS; -} - -static uint32_t flags_encode(int8_t flags, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode flags. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; - *p_offset += AD_TYPE_FIELD_SIZE; - p_encoded_data[*p_offset] = flags; - *p_offset += AD_TYPE_FLAGS_DATA_SIZE; - - return NRF_SUCCESS; -} - -static uint32_t tx_power_level_encode(int8_t tx_power_level, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode TX Power Level. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; - *p_offset += AD_TYPE_FIELD_SIZE; - p_encoded_data[*p_offset] = tx_power_level; - *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; - - return NRF_SUCCESS; -} - - -static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, - uint8_t adv_type, - uint8_t uuid_size, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - int i; - bool is_heading_written = false; - uint16_t start_pos = *p_offset; - uint16_t length; - - for (i = 0; i < p_uuid_list->uuid_cnt; i++) - { - uint32_t err_code; - uint8_t encoded_size; - ble_uuid_t uuid = p_uuid_list->p_uuids[i]; - - // Find encoded uuid size. - err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); - VERIFY_SUCCESS(err_code); - - // Check size. - if (encoded_size == uuid_size) - { - uint8_t heading_bytes = (is_heading_written) ? 0 : AD_DATA_OFFSET; - - // Check for buffer overflow - if (((*p_offset) + encoded_size + heading_bytes) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - if (!is_heading_written) - { - // Write AD structure heading. - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = adv_type; - *p_offset += AD_TYPE_FIELD_SIZE; - is_heading_written = true; - } - - // Write UUID. - err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); - VERIFY_SUCCESS(err_code); - *p_offset += encoded_size; - } - } - - if (is_heading_written) - { - // Write length. - length = (*p_offset) - (start_pos + AD_LENGTH_FIELD_SIZE); - // There is only 1 byte intended to encode length - if (length > 0x00FF) - { - return NRF_ERROR_DATA_SIZE; - } - p_encoded_data[start_pos] = (uint8_t)length; - } - - return NRF_SUCCESS; -} - - -static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, - uint8_t adv_type_16, - uint8_t adv_type_128, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - - // Encode 16 bit UUIDs. - err_code = uuid_list_sized_encode(p_uuid_list, - adv_type_16, - sizeof(uint16_le_t), - p_encoded_data, - p_offset, - max_size); - VERIFY_SUCCESS(err_code); - - // Encode 128 bit UUIDs. - err_code = uuid_list_sized_encode(p_uuid_list, - adv_type_128, - sizeof(ble_uuid128_t), - p_encoded_data, - p_offset, - max_size); - VERIFY_SUCCESS(err_code); - - return NRF_SUCCESS; -} - - -static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) -{ - // Check Minimum Connection Interval. - if ((p_conn_int->min_conn_interval < 0x0006) || - ( - (p_conn_int->min_conn_interval > 0x0c80) && - (p_conn_int->min_conn_interval != 0xffff) - ) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Check Maximum Connection Interval. - if ((p_conn_int->max_conn_interval < 0x0006) || - ( - (p_conn_int->max_conn_interval > 0x0c80) && - (p_conn_int->max_conn_interval != 0xffff) - ) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. - if ((p_conn_int->min_conn_interval != 0xffff) && - (p_conn_int->max_conn_interval != 0xffff) && - (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t err_code; - - // Check for buffer overflow. - if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // Check parameters. - err_code = conn_int_check(p_conn_int); - VERIFY_SUCCESS(err_code); - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode Minimum and Maximum Connection Intervals. - *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); - *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); - - return NRF_SUCCESS; -} - - -static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; - - // Check for buffer overflow. - if (((*p_offset) + AD_DATA_OFFSET + data_size) > max_size) - { - return NRF_ERROR_DATA_SIZE; - } - - // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) - if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode Company Identifier. - *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); - - // Encode additional manufacturer specific data. - if (p_manuf_sp_data->data.size > 0) - { - if (p_manuf_sp_data->data.p_data == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); - *p_offset += p_manuf_sp_data->data.size; - } - - return NRF_SUCCESS; -} - -// Implemented only for 16-bit UUIDs -static uint32_t service_data_encode(const ble_advdata_t * p_advdata, - uint8_t * p_encoded_data, - uint16_t * p_offset, - uint16_t max_size) -{ - uint8_t i; - - // Check parameter consistency. - if (p_advdata->p_service_data_array == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - - for (i = 0; i < p_advdata->service_data_count; i++) - { - ble_advdata_service_data_t * p_service_data; - uint32_t data_size; - - p_service_data = &p_advdata->p_service_data_array[i]; - // For now implemented only for 16-bit UUIDs - data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; - - // There is only 1 byte intended to encode length which is (data_size + AD_TYPE_FIELD_SIZE) - if (data_size > (0x00FF - AD_TYPE_FIELD_SIZE)) - { - return NRF_ERROR_DATA_SIZE; - } - - // Encode Length and AD Type. - p_encoded_data[*p_offset] = (uint8_t)(AD_TYPE_FIELD_SIZE + data_size); - *p_offset += AD_LENGTH_FIELD_SIZE; - p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; - *p_offset += AD_TYPE_FIELD_SIZE; - - // Encode service 16-bit UUID. - *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); - - // Encode additional service data. - if (p_service_data->data.size > 0) - { - if (p_service_data->data.p_data == NULL) - { - return NRF_ERROR_INVALID_PARAM; - } - memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); - *p_offset += p_service_data->data.size; - } - } - - return NRF_SUCCESS; -} - -uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, - uint8_t * const p_encoded_data, - uint16_t * const p_len) -{ - uint32_t err_code = NRF_SUCCESS; - uint16_t max_size = *p_len; - *p_len = 0; - - // Encode LE Bluetooth Device Address - if (p_advdata->include_ble_device_addr) - { - err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode appearance. - if (p_advdata->include_appearance) - { - err_code = appearance_encode(p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - //Encode Flags - if (p_advdata->flags != 0 ) - { - err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode TX power level. - if (p_advdata->p_tx_power_level != NULL) - { - err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'more available' uuid list. - if (p_advdata->uuids_more_available.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_more_available, - BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, - BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'complete' uuid list. - if (p_advdata->uuids_complete.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_complete, - BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, - BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode 'solicited service' uuid list. - if (p_advdata->uuids_solicited.uuid_cnt > 0) - { - err_code = uuid_list_encode(&p_advdata->uuids_solicited, - BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, - BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Slave Connection Interval Range. - if (p_advdata->p_slave_conn_int != NULL) - { - err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Manufacturer Specific Data. - if (p_advdata->p_manuf_specific_data != NULL) - { - err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, - p_encoded_data, - p_len, - max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode Service Data. - if (p_advdata->service_data_count > 0) - { - err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. - if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) - { - err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); - VERIFY_SUCCESS(err_code); - } - - return err_code; -} - - -static uint32_t advdata_check(const ble_advdata_t * p_advdata) -{ - // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. - if ( - ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) - ) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -static uint32_t srdata_check(const ble_advdata_t * p_srdata) -{ - // Flags shall not be included in the scan response data. - if (p_srdata->flags) - { - return NRF_ERROR_INVALID_PARAM; - } - - return NRF_SUCCESS; -} - - -uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) -{ - uint32_t err_code; - uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE; - uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE; - uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; - uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; - uint8_t * p_encoded_advdata; - uint8_t * p_encoded_srdata; - - // Encode advertising data (if supplied). - if (p_advdata != NULL) - { - err_code = advdata_check(p_advdata); - VERIFY_SUCCESS(err_code); - - err_code = ble_advdata_encode(p_advdata, encoded_advdata, &len_advdata); - VERIFY_SUCCESS(err_code); - p_encoded_advdata = encoded_advdata; - } - else - { - p_encoded_advdata = NULL; - len_advdata = 0; - } - - // Encode scan response data (if supplied). - if (p_srdata != NULL) - { - err_code = srdata_check(p_srdata); - VERIFY_SUCCESS(err_code); - - err_code = ble_advdata_encode(p_srdata, encoded_srdata, &len_srdata); - VERIFY_SUCCESS(err_code); - p_encoded_srdata = encoded_srdata; - } - else - { - p_encoded_srdata = NULL; - len_srdata = 0; - } - - // Pass encoded advertising data and/or scan response data to the stack. - return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h deleted file mode 100644 index bf7d862497..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_advdata.h +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_sdk_lib_advdata Advertising and Scan Response Data Encoder - * @{ - * @ingroup ble_sdk_lib - * @brief Functions for encoding data in the Advertising and Scan Response Data format, - * and for passing the data to the stack. - */ - -#ifndef BLE_ADVDATA_H__ -#define BLE_ADVDATA_H__ - -#include -#include -#include -#include "nrf_ble.h" -#include "app_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -#define AD_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */ -#define AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */ -#define AD_DATA_OFFSET (AD_LENGTH_FIELD_SIZE + AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */ - -#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \ - AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */ -#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */ -#define AD_TYPE_APPEARANCE_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */ -#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */ -#define AD_TYPE_FLAGS_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_TX_POWER_LEVEL_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */ -#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_CONN_INT_SIZE (AD_DATA_OFFSET + \ - AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */ -#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */ -#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */ - - -/**@brief Security Manager TK value. */ -typedef struct -{ - uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value in little-endian format. */ -} ble_advdata_tk_value_t; - -/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside - * the advertising data. */ -typedef enum -{ - BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */ - BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */ - BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */ - BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */ - BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */ -} ble_advdata_le_role_t; - -/**@brief Advertising data name type. This enumeration contains the options available for the device name inside - * the advertising data. */ -typedef enum -{ - BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */ - BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */ - BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */ -} ble_advdata_name_type_t; - -/**@brief UUID list type. */ -typedef struct -{ - uint16_t uuid_cnt; /**< Number of UUID entries. */ - ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */ -} ble_advdata_uuid_list_t; - -/**@brief Connection interval range structure. */ -typedef struct -{ - uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */ - uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */ -} ble_advdata_conn_int_t; - -/**@brief Manufacturer specific data structure. */ -typedef struct -{ - uint16_t company_identifier; /**< Company identifier code. */ - uint8_array_t data; /**< Additional manufacturer specific data. */ -} ble_advdata_manuf_data_t; - -/**@brief Service data structure. */ -typedef struct -{ - uint16_t service_uuid; /**< Service UUID. */ - uint8_array_t data; /**< Additional service data. */ -} ble_advdata_service_data_t; - -/**@brief Advertising data structure. This structure contains all options and data needed for encoding and - * setting the advertising data. */ -typedef struct -{ - ble_advdata_name_type_t name_type; /**< Type of device name. */ - uint8_t short_name_len; /**< Length of short device name (if short type is specified). */ - bool include_appearance; /**< Determines if Appearance shall be included. */ - uint8_t flags; /**< Advertising data Flags field. */ - int8_t * p_tx_power_level; /**< TX Power Level field. */ - ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */ - ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */ - ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */ - ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */ - ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */ - ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */ - uint8_t service_data_count; /**< Number of Service data structures. */ - bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */ - ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */ - ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ - uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ -#if (NRF_SD_BLE_API_VERSION > 1) - ble_gap_lesc_oob_data_t * p_lesc_data; /**< LE Secure Connections OOB data. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/ -#endif -} ble_advdata_t; - -/**@brief Function for encoding data in the Advertising and Scan Response data format - * (AD structures). - * - * @details This function encodes data into the Advertising and Scan Response data format - * (AD structures) based on the selections in the supplied structures. This function can be used to - * create a payload of Advertising packet or Scan Response packet, or a payload of NFC - * message intended for initiating the Out-of-Band pairing. - * - * @param[in] p_advdata Pointer to the structure for specifying the content of encoded data. - * @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned. - * @param[in,out] p_len \c in: Size of \p p_encoded_data buffer. - * \c out: Length of encoded data. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. - * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the - * provided buffer or some encoded AD structure is too long and its - * length cannot be encoded with one octet. - * - * @warning This API may override the application's request to use the long name and use a short name - * instead. This truncation will occur in case the long name does not fit the provided buffer size. - * The application can specify a preferred short name length if truncation is required. - * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name - * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni - * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. - * However, it should be noted that this is just a preference that the application can specify, and - * if the preference is too large to fit in the provided buffer, the name can be truncated further. - */ -uint32_t ble_advdata_encode(ble_advdata_t const * const p_advdata, - uint8_t * const p_encoded_data, - uint16_t * const p_len); - -/**@brief Function for encoding and setting the advertising data and/or scan response data. - * - * @details This function encodes advertising data and/or scan response data based on the selections - * in the supplied structures, and passes the encoded data to the stack. - * - * @param[in] p_advdata Structure for specifying the content of the advertising data. - * Set to NULL if advertising data is not to be set. - * @param[in] p_srdata Structure for specifying the content of the scan response data. - * Set to NULL if scan response data is not to be set. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata. - * @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the - * advertising packet. The maximum size of the advertisement packet - * is @ref BLE_GAP_ADV_MAX_SIZE. - * - * @warning This API may override the application's request to use the long name and use a short name - * instead. This truncation will occur in case the long name does not fit the provided buffer size. - * The application can specify a preferred short name length if truncation is required. - * For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name - * length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni - * if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. - * However, it should be noted that this is just a preference that the application can specify, and - * if the preference is too large to fit in the provided buffer, the name can be truncated further. - */ -uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata); - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_ADVDATA_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c deleted file mode 100644 index 3229571b31..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.c +++ /dev/null @@ -1,572 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_CONN_PARAMS) -#include -#include "nrf.h" -#include "sdk_errors.h" -#include "ble_hci.h" -#include "ble_err.h" -#include "ble_conn_params.h" -#include "ble_srv_common.h" -#include "ble_conn_state.h" -#include "nrf_sdh_ble.h" -#include "app_timer.h" -#include "app_util.h" - - -#define NRF_BLE_CONN_PARAMS_N_INSTANCES NRF_SDH_BLE_PERIPHERAL_LINK_COUNT //!< The number of @ref ble_conn_params_instance_t instances kept by the conn_params module. - -#if (NRF_BLE_CONN_PARAMS_N_INSTANCES < 1) -#error Invalid NRF_SDH_BLE_PERIPHERAL_LINK_COUNT value. Set it in SDK config (nrf_sdh_ble). -#endif - -/** @brief Each peripheral link has such an instance associated with it. - */ -typedef struct -{ - uint16_t conn_handle; //!< The connection handle of this link. If this is @ref BLE_CONN_HANDLE_INVALID, the instance is free. - app_timer_id_t timer_id; //!< The ID of the timer associated with this link. - uint8_t update_count; //!< The number of times the connection parameters have been attempted negotiated on this link. - uint8_t params_ok; //!< Whether the current connection parameters on this link are acceptable according to the @p preferred_conn_params, and configured maximum deviations. - ble_gap_conn_params_t preferred_conn_params; //!< The desired connection parameters for this link. -} ble_conn_params_instance_t; - -static app_timer_t m_timer_data[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{{0}}}; //!< Data needed for timers. -static ble_conn_params_instance_t m_conn_params_instances[NRF_BLE_CONN_PARAMS_N_INSTANCES] = {{0}}; //!< Configuration data for each connection. -static ble_conn_params_init_t m_conn_params_config; //!< Configuration as provided by the application during intialization. -static ble_gap_conn_params_t m_preferred_conn_params; //!< The preferred connection parameters as specified during initialization. -//lint -esym(551, m_preferred_conn_params) "Not accessed" - - -/**@brief Function for retrieving the conn_params instance belonging to a conn_handle - * - * @params[in] conn_handle The connection handle to retrieve the instance of. - * - * @return A pointer to the instance, or NULL if no instance was found with that conn_handle. - */ -static ble_conn_params_instance_t * instance_get(uint16_t conn_handle) -{ - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - if (m_conn_params_instances[i].conn_handle == conn_handle) - { - return &m_conn_params_instances[i]; - } - } - //lint -restore - return NULL; -} - - -/**@brief Function for initializing an instance, and associating it with a conn_handle. - * - * @params[in] p_instance The instance to initialize and associate. - * @params[in] conn_handle The connection handle to associate with. - */ -static __INLINE void instance_claim(ble_conn_params_instance_t * p_instance, uint16_t conn_handle) -{ - p_instance->conn_handle = conn_handle; - p_instance->update_count = 0; - p_instance->preferred_conn_params = m_preferred_conn_params; -} - - -/**@brief Function for freeing an instance. - * - * @params[in] p_instance The instance to free. - */ -static __INLINE void instance_free(ble_conn_params_instance_t * p_instance) -{ - p_instance->conn_handle = BLE_CONN_HANDLE_INVALID; -} - - -/**@brief Function for validating a set of connection parameters against the preferred parameters. - * - * @param[in] p_preferred_conn_params The desired parameters. - * @param[in] p_actual_conn_params The parameters to validate. - * @param[in] max_slave_latency_err The amount of discrepancy in slave latency, in number of - * connection intervals, that will be accepted. - * @param[in] max_sup_timeout_err The amount of discrepancy in supervision timeout, in tens of - * milliseconds, that will be accepted. - * - * @return Whether the params in @p p_actual_conn_params are acceptable given the other parameters. - */ -static bool is_conn_params_ok(ble_gap_conn_params_t const * p_preferred_conn_params, - ble_gap_conn_params_t const * p_actual_conn_params, - uint16_t max_slave_latency_err, - uint16_t max_sup_timeout_err) -{ - uint32_t max_allowed_sl = p_preferred_conn_params->slave_latency + max_slave_latency_err; - uint32_t min_allowed_sl = p_preferred_conn_params->slave_latency - - MIN(max_slave_latency_err, p_preferred_conn_params->slave_latency); - uint32_t max_allowed_to = p_preferred_conn_params->conn_sup_timeout + max_sup_timeout_err; - uint32_t min_allowed_to = p_preferred_conn_params->conn_sup_timeout - - MIN(max_sup_timeout_err, p_preferred_conn_params->conn_sup_timeout); - - // Check if interval is within the acceptable range. - // NOTE: Using max_conn_interval in the received event data because this contains - // the client's connection interval. - if ((p_actual_conn_params->max_conn_interval < p_preferred_conn_params->min_conn_interval) - || (p_actual_conn_params->max_conn_interval > p_preferred_conn_params->max_conn_interval)) - { - return false; - } - - // Check if slave latency is within the acceptable deviation. - if ((p_actual_conn_params->slave_latency < min_allowed_sl) - || (p_actual_conn_params->slave_latency > max_allowed_sl)) - { - return false; - } - - // Check if supervision timeout is within the acceptable deviation. - if ((p_actual_conn_params->conn_sup_timeout < min_allowed_to) - || (p_actual_conn_params->conn_sup_timeout > max_allowed_to)) - { - return false; - } - - return true; -} - - -static void send_error_evt(ret_code_t err_code) -{ - if (m_conn_params_config.error_handler != NULL) - { - m_conn_params_config.error_handler(err_code); - } -} - - -/**@brief Function for sending a conn_param_update request on-air, and handling errors. - * - * @param[in] conn_handle Connection to send request on. - * @param[in] p_new_conn_params Connection parameters to request. - * - * @return Whether the request was successfully sent. - */ -static bool send_update_request(uint16_t conn_handle, ble_gap_conn_params_t * p_new_conn_params) -{ - ret_code_t err_code; - - err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_conn_params); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) // NRF_ERROR_BUSY means another conn_param_update request is pending. - { - send_error_evt(err_code); - } - - return (err_code == NRF_SUCCESS); -} - - -/**@brief Function called after conn_params_update_delay has happened. This is triggered by app_timer. - * - * @param[in] p_context Context identifying which connection this is for. - */ -static void update_timeout_handler(void * p_context) -{ - uint32_t conn_handle = (uint32_t)p_context; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Check if we have reached the maximum number of attempts - if (p_instance->update_count < m_conn_params_config.max_conn_params_update_count) - { - bool update_sent = send_update_request(conn_handle, &p_instance->preferred_conn_params); - if (update_sent) - { - p_instance->update_count++; - } - } - else - { - p_instance->update_count = 0; - - // Negotiation failed, disconnect automatically if this has been configured - if (m_conn_params_config.disconnect_on_fail) - { - ret_code_t err_code; - - err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) // NRF_ERROR_INVALID_STATE means disconnect is already in progress. - { - send_error_evt(err_code); - } - } - - // Notify the application that the procedure has failed - if (m_conn_params_config.evt_handler != NULL) - { - ble_conn_params_evt_t evt; - - evt.evt_type = BLE_CONN_PARAMS_EVT_FAILED; - evt.conn_handle = conn_handle; - m_conn_params_config.evt_handler(&evt); - } - } - } -} - - -ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init) -{ - ret_code_t err_code; - - VERIFY_PARAM_NOT_NULL(p_init); - - m_conn_params_config = *p_init; - m_conn_params_config.p_conn_params = &m_preferred_conn_params; - - if (p_init->p_conn_params != NULL) - { - // Set the connection params in stack. - err_code = sd_ble_gap_ppcp_set(p_init->p_conn_params); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - m_preferred_conn_params = *p_init->p_conn_params; - } - else - { - // Get the (default) connection params from stack. - err_code = sd_ble_gap_ppcp_get(&m_preferred_conn_params); - if (err_code != NRF_SUCCESS) - { - return err_code; - } - } - - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - ble_conn_params_instance_t * p_instance = &m_conn_params_instances[i]; - - instance_free(p_instance); - p_instance->timer_id = &m_timer_data[i]; - - err_code = app_timer_create(&p_instance->timer_id, - APP_TIMER_MODE_SINGLE_SHOT, - update_timeout_handler); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - } - //lint -restore - - return NRF_SUCCESS; -} - - -ret_code_t ble_conn_params_stop(void) -{ - ret_code_t err_code; - - //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_N_INSTANCES is 0 - for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_N_INSTANCES; i++) - { - err_code = app_timer_stop(m_conn_params_instances[i].timer_id); - switch (err_code) - { - case NRF_SUCCESS: - /* do nothing */ - break; - - case NRF_ERROR_INVALID_STATE: - /* do nothing */ - break; - - case NRF_ERROR_NO_MEM: - return NRF_ERROR_BUSY; - - case NRF_ERROR_INVALID_PARAM: - /* fallthrough */ - default: - return NRF_ERROR_INTERNAL; - } - } - //lint -restore - return NRF_SUCCESS; -} - - -/**@brief Function for taking appropriate action based on the current state of connection parameters. - * - * @param[in] conn_handle Connection to handle. - * @param[in] p_instance Configuration for the connection. - */ -static void conn_params_negotiation(uint16_t conn_handle, ble_conn_params_instance_t * p_instance) - { - // Start negotiation if the received connection parameters are not acceptable - if (!p_instance->params_ok) - { - ret_code_t err_code; - uint32_t timeout_ticks; - - if (p_instance->update_count == 0) - { - // First connection parameter update - timeout_ticks = m_conn_params_config.first_conn_params_update_delay; - } - else - { - timeout_ticks = m_conn_params_config.next_conn_params_update_delay; - } - - err_code = app_timer_start(p_instance->timer_id, timeout_ticks, (void *)(uint32_t)conn_handle); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - } - else - { - p_instance->update_count = 0; - - // Notify the application that the procedure has succeeded - if (m_conn_params_config.evt_handler != NULL) - { - ble_conn_params_evt_t evt; - - evt.evt_type = BLE_CONN_PARAMS_EVT_SUCCEEDED; - evt.conn_handle = conn_handle; - m_conn_params_config.evt_handler(&evt); - } - } -} - - -/**@brief Function for handling a connection event from the SoftDevice. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_connect(ble_evt_t const * p_ble_evt) -{ - uint8_t role = p_ble_evt->evt.gap_evt.params.connected.role; - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - - if (role != BLE_GAP_ROLE_PERIPH) - { - return; - } - - ble_conn_params_instance_t * p_instance = instance_get(BLE_CONN_HANDLE_INVALID); - - if (p_instance == NULL) - { - send_error_evt(NRF_ERROR_NO_MEM); - return; - } - - instance_claim(p_instance, conn_handle); - p_instance->params_ok = is_conn_params_ok(&p_instance->preferred_conn_params, - &p_ble_evt->evt.gap_evt.params.connected.conn_params, - NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, - NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); - - // Check if we shall handle negotiation on connect - if (m_conn_params_config.start_on_notify_cccd_handle == BLE_GATT_HANDLE_INVALID) - { - conn_params_negotiation(conn_handle, p_instance); - } -} - - -/**@brief Function for handling a disconnection event from the SoftDevice. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_disconnect(ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Stop timer if running - err_code = app_timer_stop(p_instance->timer_id); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - - instance_free(p_instance); - } -} - - -/**@brief Function for handling a GATT write event from the SoftDevice. - * - * @details To provide the start_on_notify_cccd_handle functionality. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_write(ble_evt_t const * p_ble_evt) -{ - ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; - - // Check if this is the correct CCCD - if ( - (p_evt_write->handle == m_conn_params_config.start_on_notify_cccd_handle) - && - (p_evt_write->len == 2) - ) - { - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - // Check if this is a 'start notification' - if (ble_srv_is_notification_enabled(p_evt_write->data)) - { - // Do connection parameter negotiation if necessary - conn_params_negotiation(conn_handle, p_instance); - } - else - { - ret_code_t err_code; - - // Stop timer if running - err_code = app_timer_stop(p_instance->timer_id); - if (err_code != NRF_SUCCESS) - { - send_error_evt(err_code); - } - } - } - } -} - - -/**@brief Function for handling a connection parameter update event from the SoftDevice. - * - * @details This event means the peer central has changed the connection parameters or declined our - * request. - * - * @param[in] p_ble_evt Event from the SoftDevice. - */ -static void on_conn_params_update(ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_instance != NULL) - { - p_instance->params_ok = is_conn_params_ok( - &p_instance->preferred_conn_params, - &p_ble_evt->evt.gap_evt.params.conn_param_update.conn_params, - NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION, - NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION); - - conn_params_negotiation(conn_handle, p_instance); - } -} - - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connect(p_ble_evt); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnect(p_ble_evt); - break; - - case BLE_GATTS_EVT_WRITE: - on_write(p_ble_evt); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE: - on_conn_params_update(p_ble_evt); - break; - - default: - // No implementation needed. - break; - } -} - - -ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, - ble_gap_conn_params_t * p_new_params) -{ - ret_code_t err_code = BLE_ERROR_INVALID_CONN_HANDLE; - ble_conn_params_instance_t * p_instance = instance_get(conn_handle); - - if (p_new_params == NULL) - { - p_new_params = &m_preferred_conn_params; - } - - if (p_instance != NULL) - { - // Send request to central. - err_code = sd_ble_gap_conn_param_update(conn_handle, p_new_params); - if (err_code == NRF_SUCCESS) - { - p_instance->params_ok = false; - p_instance->update_count = 1; - p_instance->preferred_conn_params = *p_new_params; - } - } - - return err_code; -} - -NRF_SDH_BLE_OBSERVER(m_ble_observer, BLE_CONN_PARAMS_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - -#endif //ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h deleted file mode 100644 index 0e2024c0eb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_params.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_conn_params Connection Parameters Negotiation - * @{ - * @ingroup ble_sdk_lib - * @brief Module for initiating and executing a connection parameters negotiation procedure. - */ - -#ifndef BLE_CONN_PARAMS_H__ -#define BLE_CONN_PARAMS_H__ - -#include -#include "nrf_ble.h" -#include "ble_srv_common.h" -#include "sdk_errors.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Connection Parameters Module event type. */ -typedef enum -{ - BLE_CONN_PARAMS_EVT_FAILED, //!< Negotiation procedure failed. - BLE_CONN_PARAMS_EVT_SUCCEEDED //!< Negotiation procedure succeeded. -} ble_conn_params_evt_type_t; - -/**@brief Connection Parameters Module event. */ -typedef struct -{ - ble_conn_params_evt_type_t evt_type; //!< Type of event. - uint16_t conn_handle; //!< Connection the event refers to. -} ble_conn_params_evt_t; - -/**@brief Connection Parameters Module event handler type. */ -typedef void (*ble_conn_params_evt_handler_t) (ble_conn_params_evt_t * p_evt); - -/**@brief Connection Parameters Module init structure. This contains all options and data needed for - * initialization of the connection parameters negotiation module. */ -typedef struct -{ - ble_gap_conn_params_t * p_conn_params; //!< Pointer to the connection parameters desired by the application. When calling ble_conn_params_init, if this parameter is set to NULL, the connection parameters will be fetched from host. - uint32_t first_conn_params_update_delay; //!< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (in number of timer ticks). - uint32_t next_conn_params_update_delay; //!< Time between each call to sd_ble_gap_conn_param_update after the first (in number of timer ticks). Recommended value 30 seconds as per BLUETOOTH SPECIFICATION Version 4.0. - uint8_t max_conn_params_update_count; //!< Number of attempts before giving up the negotiation. - uint16_t start_on_notify_cccd_handle; //!< If procedure is to be started when notification is started, set this to the handle of the corresponding CCCD. Set to BLE_GATT_HANDLE_INVALID if procedure is to be started on connect event. - bool disconnect_on_fail; //!< Set to TRUE if a failed connection parameters update shall cause an automatic disconnection, set to FALSE otherwise. - ble_conn_params_evt_handler_t evt_handler; //!< Event handler to be called for handling events in the Connection Parameters. - ble_srv_error_handler_t error_handler; //!< Function to be called in case of an error. -} ble_conn_params_init_t; - - -/**@brief Function for initializing the Connection Parameters module. - * - * @note If the negotiation procedure should be triggered when notification/indication of - * any characteristic is enabled by the peer, then this function must be called after - * having initialized the services. - * - * @param[in] p_init This contains information needed to initialize this module. - * - * @retval NRF_SUCCESS Successful initialization. - * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. - * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. - * @retval NRF_ERROR_NULL @p p_init was NULL. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init); - -/**@brief Function for stopping the Connection Parameters module. - * - * @details This function is intended to be used by the application to clean up the connection - * parameters update module. This will stop the connection parameters update timer if - * running, thereby preventing any impending connection parameters update procedure. This - * function must be called by the application when it needs to clean itself up (for - * example, before disabling the bluetooth SoftDevice) so that an unwanted timer expiry - * event can be avoided. - * - * @retval NRF_SUCCESS Successfully stopped module. - * @retval NRF_ERROR_BUSY Could not complete operation at this time. Try again later. - Note that some timers may have been disabled. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t ble_conn_params_stop(void); - -/**@brief Function for changing the current connection parameters to a new set. - * - * @details Use this function to change the connection parameters to a new set of parameter - * (ie different from the ones given at init of the module). - * This function is useful for scenario where most of the time the application - * needs a relatively big connection interval, and just sometimes, for a temporary - * period requires shorter connection interval, for example to transfer a higher - * amount of data. - * If the given parameters does not match the current connection's parameters - * this function initiates a new negotiation. - * - * @param[in] conn_handle The connection to change connection parameters on. - * @param[in] p_new_params This contains the new connections parameters to setup. - * - * @retval NRF_SUCCESS Successfully started Connection Parameter update procedure. - * @retval NRF_ERROR_INVALID_ADDR The provided Connection Parameters pointer is invalid. - * @retval NRF_ERROR_INVALID_PARAM The provided Connection Parameters are not valid. - * @retval BLE_ERROR_INVALID_CONN_HANDLE The provided connection handle is invalid. - * @retval NRF_ERROR_INVALID_STATE The connection is not in a state where this operation can - * performed. - * @retval NRF_ERROR_BUSY Could not start operation at this time. Try again later. - * @retval NRF_ERROR_NO_MEM The SoftDevice lacks the memory to perform the action. - */ -ret_code_t ble_conn_params_change_conn_params(uint16_t conn_handle, - ble_gap_conn_params_t * p_new_params); - -#ifdef __cplusplus -} -#endif - -#endif // BLE_CONN_PARAMS_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c deleted file mode 100644 index 47f1d7c9e6..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.c +++ /dev/null @@ -1,444 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "ble_conn_state.h" -#include -#include -#include -#include "nrf_ble.h" -#include "sdk_mapped_flags.h" -#include "app_error.h" -#include "nrf_sdh_ble.h" - - -#if defined(__CC_ARM) - #pragma push - #pragma anon_unions -#elif defined(__ICCARM__) - #pragma language=extended -#elif defined(__GNUC__) - /* anonymous unions are enabled by default */ -#endif - - -#define BLE_CONN_STATE_N_DEFAULT_FLAGS 5 /**< The number of flags kept for each connection, excluding user flags. */ -#define BLE_CONN_STATE_N_FLAGS (BLE_CONN_STATE_N_DEFAULT_FLAGS + BLE_CONN_STATE_N_USER_FLAGS) /**< The number of flags kept for each connection, including user flags. */ - -/**@brief Structure containing all the flag collections maintained by the Connection State module. - */ -typedef struct -{ - sdk_mapped_flags_t valid_flags; /**< Flags indicating which connection handles are valid. */ - sdk_mapped_flags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */ - sdk_mapped_flags_t central_flags; /**< Flags indicating in which connections the local device is the central. */ - sdk_mapped_flags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */ - sdk_mapped_flags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */ - sdk_mapped_flags_t user_flags[BLE_CONN_STATE_N_USER_FLAGS]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */ -} ble_conn_state_flag_collections_t; - - -/**@brief Structure containing the internal state of the Connection State module. - */ -typedef struct -{ - uint32_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */ - uint16_t valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */ - union - { - ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */ - sdk_mapped_flags_t flag_array[BLE_CONN_STATE_N_FLAGS]; /**< Flag collections as array to allow use of @ref sdk_mapped_flags_bulk_update_by_key() when setting all flags. */ - }; -} ble_conn_state_t; - - -#if defined(__CC_ARM) - #pragma pop -#elif defined(__ICCARM__) - /* leave anonymous unions enabled */ -#elif defined(__GNUC__) - /* anonymous unions are enabled by default */ -#endif - - -static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */ - - -/**@brief Function for resetting all internal memory to the values it had at initialization. - */ -void bcs_internal_state_reset(void) -{ - memset( &m_bcs, 0, sizeof(ble_conn_state_t) ); -} - - -/**@brief Function for activating a connection record. - * - * @param p_record The record to activate. - * @param conn_handle The connection handle to copy into the record. - * @param role The role of the connection. - * - * @return whether the record was activated successfully. - */ -static bool record_activate(uint16_t conn_handle) -{ - uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags); - - if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX) - { - m_bcs.valid_conn_handles[available_index] = conn_handle; - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.connected_flags, - conn_handle, - 1); - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.valid_flags, - conn_handle, - 1); - - return true; - } - - return false; -} - - -/**@brief Function for marking a connection record as invalid and resetting the values. - * - * @param p_record The record to invalidate. - */ -static void record_invalidate(uint16_t conn_handle) -{ - sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles, - m_bcs.flag_array, - BLE_CONN_STATE_N_FLAGS, - conn_handle, - 0); -} - - -/**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED. - * - * @param p_record The record of the connection to set as disconnected. - */ -static void record_set_disconnected(uint16_t conn_handle) -{ - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.connected_flags, - conn_handle, - 0); -} - - -/**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED - * connection status - */ -static void record_purge_disconnected() -{ - sdk_mapped_flags_key_list_t disconnected_list; - - disconnected_list = sdk_mapped_flags_key_list_get( - m_bcs.valid_conn_handles, - (~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags)); - - for (uint32_t i = 0; i < disconnected_list.len; i++) - { - record_invalidate(disconnected_list.flag_keys[i]); - } -} - - -/**@brief Function for checking if a user flag has been acquired. - * - * @param[in] flag_id Which flag to check. - * - * @return Whether the flag has been acquired. - */ -static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id) -{ - return ((m_bcs.acquired_flags & (1 << flag_id)) != 0); -} - - -/**@brief Function for marking a user flag as acquired. - * - * @param[in] flag_id Which flag to mark. - */ -static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id) -{ - m_bcs.acquired_flags |= (1 << flag_id); -} - - -void ble_conn_state_init(void) -{ - bcs_internal_state_reset(); -} - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - record_purge_disconnected(); - - if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) ) - { - // No more records available. Should not happen. - APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); - } -#if !defined (S112) - else - { - bool is_central = - (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL); - - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.central_flags, - p_ble_evt->evt.gap_evt.conn_handle, - is_central); - } -#endif // !defined (S112) - - break; - - case BLE_GAP_EVT_DISCONNECTED: - record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle); - break; - - case BLE_GAP_EVT_CONN_SEC_UPDATE: - sdk_mapped_flags_update_by_key( - m_bcs.valid_conn_handles, - &m_bcs.flags.encrypted_flags, - p_ble_evt->evt.gap_evt.conn_handle, - (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1)); - sdk_mapped_flags_update_by_key( - m_bcs.valid_conn_handles, - &m_bcs.flags.mitm_protected_flags, - p_ble_evt->evt.gap_evt.conn_handle, - (p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2)); - break; - } -} - -NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_CONN_STATE_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - - -bool ble_conn_state_valid(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle); -} - - -uint8_t ble_conn_state_role(uint16_t conn_handle) -{ - uint8_t role = BLE_GAP_ROLE_INVALID; - - if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) ) - { - bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.central_flags, - conn_handle); -#if !defined (S112) - role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH; -#else - role = BLE_GAP_ROLE_PERIPH; - UNUSED_VARIABLE(central); -#endif // !defined (S112) - } - - return role; -} - - -ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle) -{ - ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID; - bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle); - - if (valid) - { - bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.connected_flags, - conn_handle); - - conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED; - } - - return conn_status; -} - - -bool ble_conn_state_encrypted(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.encrypted_flags, - conn_handle); -} - - -bool ble_conn_state_mitm_protected(uint16_t conn_handle) -{ - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.mitm_protected_flags, - conn_handle); -} - - -uint32_t ble_conn_state_n_connections(void) -{ - return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags); -} - - -uint32_t ble_conn_state_n_centrals(void) -{ - return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -uint32_t ble_conn_state_n_peripherals(void) -{ - return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, - (m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void) -{ - return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, - (~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags)); -} - - -uint8_t ble_conn_state_conn_idx(uint16_t conn_handle) -{ - uint8_t index; - if (sdk_mapped_flags_get_by_key_w_idx(m_bcs.valid_conn_handles, - m_bcs.flags.valid_flags, - conn_handle, - &index)) - { - return index; - } - else - { - return BLE_CONN_STATE_MAX_CONNECTIONS; - } -} - - -ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void) -{ - for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0; - i < BLE_CONN_STATE_N_USER_FLAGS; - i++) - { - if ( !user_flag_is_acquired(i) ) - { - user_flag_acquire(i); - return i; - } - } - - return BLE_CONN_STATE_USER_FLAG_INVALID; -} - - -bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id) -{ - if (user_flag_is_acquired(flag_id)) - { - return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, - m_bcs.flags.user_flags[flag_id], - conn_handle); - } - else - { - return false; - } -} - - -void ble_conn_state_user_flag_set(uint16_t conn_handle, - ble_conn_state_user_flag_id_t flag_id, - bool value) -{ - if (user_flag_is_acquired(flag_id)) - { - sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles, - &m_bcs.flags.user_flags[flag_id], - conn_handle, - value); - } -} - - -sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id) -{ - if ( user_flag_is_acquired(flag_id) ) - { - return m_bcs.flags.user_flags[flag_id]; - } - else - { - return 0; - } -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h deleted file mode 100644 index 878b8d838a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_conn_state.h +++ /dev/null @@ -1,317 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file - * - * @defgroup ble_conn_state Connection state - * @ingroup ble_sdk_lib - * @{ - * @brief Module for storing data on BLE connections. - * - * @details This module stores certain states for each connection, which can be queried by - * connection handle. The module uses BLE events to keep the states updated. - * - * In addition to the preprogrammed states, this module can also keep track of a number of - * binary user states, or user flags. These are reset to 0 for new connections, but - * otherwise not touched by this module. - * - * This module uses the @ref sdk_mapped_flags module, with connection handles as keys and - * the connection states as flags. - * - * @note A connection handle is not immediately invalidated when it is disconnected. Certain states, - * such as the role, can still be queried until the next time a new connection is established - * to any device. - * - */ - -#ifndef BLE_CONN_STATE_H__ -#define BLE_CONN_STATE_H__ - -#include -#include -#include "nrf_ble.h" -#include "sdk_mapped_flags.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Connection handle statuses. - */ -typedef enum -{ - BLE_CONN_STATUS_INVALID, /**< The connection handle is invalid. */ - BLE_CONN_STATUS_DISCONNECTED, /**< The connection handle refers to a connection that has been disconnected, but not yet invalidated. */ - BLE_CONN_STATUS_CONNECTED, /**< The connection handle refers to an active connection. */ -} ble_conn_state_status_t; - -#define BLE_CONN_STATE_MAX_CONNECTIONS 20 /**< The maximum number of connections supported. */ -#define BLE_CONN_STATE_N_USER_FLAGS 24 /**< The number of available user flags. */ - - -/**@brief One ID for each user flag collection. - * - * @details These IDs are used to identify user flag collections in the API calls. - */ -typedef enum -{ - BLE_CONN_STATE_USER_FLAG0 = 0, - BLE_CONN_STATE_USER_FLAG1, - BLE_CONN_STATE_USER_FLAG2, - BLE_CONN_STATE_USER_FLAG3, - BLE_CONN_STATE_USER_FLAG4, - BLE_CONN_STATE_USER_FLAG5, - BLE_CONN_STATE_USER_FLAG6, - BLE_CONN_STATE_USER_FLAG7, - BLE_CONN_STATE_USER_FLAG8, - BLE_CONN_STATE_USER_FLAG9, - BLE_CONN_STATE_USER_FLAG10, - BLE_CONN_STATE_USER_FLAG11, - BLE_CONN_STATE_USER_FLAG12, - BLE_CONN_STATE_USER_FLAG13, - BLE_CONN_STATE_USER_FLAG14, - BLE_CONN_STATE_USER_FLAG15, - BLE_CONN_STATE_USER_FLAG16, - BLE_CONN_STATE_USER_FLAG17, - BLE_CONN_STATE_USER_FLAG18, - BLE_CONN_STATE_USER_FLAG19, - BLE_CONN_STATE_USER_FLAG20, - BLE_CONN_STATE_USER_FLAG21, - BLE_CONN_STATE_USER_FLAG22, - BLE_CONN_STATE_USER_FLAG23, - BLE_CONN_STATE_USER_FLAG_INVALID, -} ble_conn_state_user_flag_id_t; - - -/** - * @defgroup ble_conn_state_functions BLE connection state functions - * @{ - */ - - -/**@brief Function for initializing or resetting the module. - * - * @details This function sets all states to their default, removing all records of connection handles. - */ -void ble_conn_state_init(void); - - -/**@brief Function for querying whether a connection handle represents a valid connection. - * - * @details A connection might be valid and have a BLE_CONN_STATUS_DISCONNECTED status. - * Those connections are invalidated after a new connection occurs. - * - * @param[in] conn_handle Handle of the connection. - * - * @retval true If conn_handle represents a valid connection, thus a connection for which - we have a record. - * @retval false If conn_handle is @ref BLE_GAP_ROLE_INVALID, or if it has never been recorded. - */ -bool ble_conn_state_valid(uint16_t conn_handle); - - -/**@brief Function for querying the role of the local device in a connection. - * - * @param[in] conn_handle Handle of the connection to get the role for. - * - * @return The role of the local device in the connection (see @ref BLE_GAP_ROLES). - * If conn_handle is not valid, the function returns BLE_GAP_ROLE_INVALID. - */ -uint8_t ble_conn_state_role(uint16_t conn_handle); - - -/**@brief Function for querying the status of a connection. - * - * @param[in] conn_handle Handle of the connection. - * - * @return The status of the connection. - * If conn_handle is not valid, the function returns BLE_CONN_STATE_INVALID. - */ -ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle); - - -/**@brief Function for querying whether a connection is encrypted. - * - * @param[in] conn_handle Handle of connection to get the encryption state for. - * - * @retval true If the connection is encrypted. - * @retval false If the connection is not encrypted or conn_handle is invalid. - */ -bool ble_conn_state_encrypted(uint16_t conn_handle); - - -/**@brief Function for querying whether a connection encryption is protected from Man in the Middle - * attacks. - * - * @param[in] conn_handle Handle of connection to get the MITM state for. - * - * @retval true If the connection is encrypted with MITM protection. - * @retval false If the connection is not encrypted, or encryption is not MITM protected, or - * conn_handle is invalid. - */ -bool ble_conn_state_mitm_protected(uint16_t conn_handle); - - -/**@brief Function for querying the total number of connections. - * - * @return The total number of valid connections for which the module has a record. - */ -uint32_t ble_conn_state_n_connections(void); - - -/**@brief Function for querying the total number of connections in which the role of the local - * device is @ref BLE_GAP_ROLE_CENTRAL. - * - * @return The number of connections in which the role of the local device is - * @ref BLE_GAP_ROLE_CENTRAL. - */ -uint32_t ble_conn_state_n_centrals(void); - - -/**@brief Function for querying the total number of connections in which the role of the local - * device is @ref BLE_GAP_ROLE_PERIPH. - * - * @return The number of connections in which the role of the local device is - * @ref BLE_GAP_ROLE_PERIPH. - */ -uint32_t ble_conn_state_n_peripherals(void); - - -/**@brief Function for obtaining a list of all connection handles for which the module has a record. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record. - */ -sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void); - - -/**@brief Function for obtaining a list of connection handles in which the role of the local - * device is @ref BLE_GAP_ROLE_CENTRAL. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record and in which - * the role of local device is @ref BLE_GAP_ROLE_CENTRAL. - */ -sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void); - - -/**@brief Function for obtaining the handle for the connection in which the role of the local device - * is @ref BLE_GAP_ROLE_PERIPH. - * - * @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED. - * - * @return A list of all valid connection handles for which the module has a record and in which - * the role of local device is @ref BLE_GAP_ROLE_PERIPH. - */ -sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void); - - -/**@brief Function for translating a connection handle to a value that can be used as an array index. - * - * @details Function for mapping connection handles onto the range <0 - MAX_CONNECTIONS>. - * - * @note The index will be the same as long as a connection is invalid. A subsequent connection with - * the same connection handle might have a different index. - * - * @param[in] conn_handle The connection for which to retrieve an index. - * - * @return An index unique to this connection. Or @ref BLE_CONN_STATE_MAX_CONNECTIONS if - * @p conn_handle refers to an invalid connection. - */ -uint8_t ble_conn_state_conn_idx(uint16_t conn_handle); - - -/**@brief Function for obtaining exclusive access to one of the user flag collections. - * - * @details The acquired collection contains one flag for each connection. These flags can be set - * and read individually for each connection. - * - * The state of user flags will not be modified by the connection state module, except to - * set it to 0 for a connection when that connection is invalidated. - * - * @return The ID of the acquired flag, or BLE_CONN_STATE_USER_FLAG_INVALID if none are available. - */ -ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void); - - -/**@brief Function for reading the value of a user flag. - * - * @param[in] conn_handle Handle of connection to get the flag state for. - * @param[in] flag_id Which flag to get the state for. - * - * @return The state of the flag. If conn_handle is invalid, the function returns false. - */ -bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id); - - -/**@brief Function for setting the value of a user flag. - * - * @param[in] conn_handle Handle of connection to set the flag state for. - * @param[in] flag_id Which flag to set the state for. - * @param[in] value Value to set the flag state to. - */ -void ble_conn_state_user_flag_set(uint16_t conn_handle, - ble_conn_state_user_flag_id_t flag_id, - bool value); - - -/**@brief Function for getting the state of a user flag for all connection handles. - * - * @details The returned collection can be used with the @ref sdk_mapped_flags API. The returned - * collection is a copy, so modifying it has no effect on the conn_state module. - * - * @param[in] flag_id Which flag to get states for. - * - * @return The collection of flag states. The collection is always all zeros when the flag_id is - * unregistered. - */ -sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id); - -/** @} */ -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif /* BLE_CONN_STATE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h deleted file mode 100644 index 762784c11a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_date_time.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2011 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! -* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile -* qualification listings, this section of source code must not be modified. -*/ - -/** @file - * @brief Contains definition of ble_date_time structure. - */ - -/** @file - * - * @defgroup ble_sdk_srv_date_time BLE Date Time characteristic type - * @{ - * @ingroup ble_sdk_lib - * @brief Definition of ble_date_time_t type. - */ - -#ifndef BLE_DATE_TIME_H__ -#define BLE_DATE_TIME_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Date and Time structure. */ -typedef struct -{ - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hours; - uint8_t minutes; - uint8_t seconds; -} ble_date_time_t; - -static __INLINE uint8_t ble_date_time_encode(const ble_date_time_t * p_date_time, - uint8_t * p_encoded_data) -{ - uint8_t len = uint16_encode(p_date_time->year, p_encoded_data); - - p_encoded_data[len++] = p_date_time->month; - p_encoded_data[len++] = p_date_time->day; - p_encoded_data[len++] = p_date_time->hours; - p_encoded_data[len++] = p_date_time->minutes; - p_encoded_data[len++] = p_date_time->seconds; - - return len; -} - -static __INLINE uint8_t ble_date_time_decode(ble_date_time_t * p_date_time, - const uint8_t * p_encoded_data) -{ - uint8_t len = sizeof(uint16_t); - - p_date_time->year = uint16_decode(p_encoded_data); - p_date_time->month = p_encoded_data[len++]; - p_date_time->day = p_encoded_data[len++]; - p_date_time->hours = p_encoded_data[len++]; - p_date_time->minutes = p_encoded_data[len++]; - p_date_time->seconds = p_encoded_data[len++]; - - return len; -} - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_DATE_TIME_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h deleted file mode 100644 index 3b35773e0b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_gatt_db.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/**@file - * - * @defgroup ble_sdk_lib_gatt_db GATT Database Service Structure - * @{ - * @ingroup ble_sdk_lib - */ - -#ifndef BLE_GATT_DB_H__ -#define BLE_GATT_DB_H__ - -#include -#include "nrf_ble.h" -#include "ble_gattc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_GATT_DB_MAX_CHARS 6 /**< The maximum number of characteristics present in a service record. */ - -/**@brief Structure for holding the characteristic and the handle of its CCCD present on a server. - */ -typedef struct -{ - ble_gattc_char_t characteristic; /**< Structure containing information about the characteristic. */ - uint16_t cccd_handle; /**< CCCD Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a CCCD is not present at the server. */ - uint16_t ext_prop_handle; /**< Extended Properties Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if an Extended Properties descriptor is not present at the server. */ - uint16_t user_desc_handle; /**< User Description Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a User Description descriptor is not present at the server. */ - uint16_t report_ref_handle; /**< Report Reference Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a Report Reference descriptor is not present at the server. */ -} ble_gatt_db_char_t; - -/**@brief Structure for holding information about the service and the characteristics present on a - * server. - */ -typedef struct -{ - ble_uuid_t srv_uuid; /**< UUID of the service. */ - uint8_t char_count; /**< Number of characteristics present in the service. */ - ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */ - ble_gatt_db_char_t charateristics[BLE_GATT_DB_MAX_CHARS]; /**< Array of information related to the characteristics present in the service. This list can extend further than one. */ -} ble_gatt_db_srv_t; - - -#ifdef __cplusplus -} -#endif - -#endif /* BLE_GATT_DB_H__ */ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h deleted file mode 100644 index ca259f1450..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_sensor_location.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! -* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile -* qualification listings, this section of source code must not be modified. -*/ - -#ifndef BLE_SENSOR_LOCATION_H__ -#define BLE_SENSOR_LOCATION_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - BLE_SENSOR_LOCATION_OTHER = 0 , /**<-- Other */ - BLE_SENSOR_LOCATION_TOP_OF_SHOE = 1 , /**<-- Top of shoe */ - BLE_SENSOR_LOCATION_IN_SHOE = 2 , /**<-- In shoe */ - BLE_SENSOR_LOCATION_HIP = 3 , /**<-- Hip */ - BLE_SENSOR_LOCATION_FRONT_WHEEL = 4 , /**<-- Front Wheel */ - BLE_SENSOR_LOCATION_LEFT_CRANK = 5 , /**<-- Left Crank */ - BLE_SENSOR_LOCATION_RIGHT_CRANK = 6 , /**<-- Right Crank */ - BLE_SENSOR_LOCATION_LEFT_PEDAL = 7 , /**<-- Left Pedal */ - BLE_SENSOR_LOCATION_RIGHT_PEDAL = 8 , /**<-- Right Pedal */ - BLE_SENSOR_LOCATION_FRONT_HUB = 9 , /**<-- Front Hub */ - BLE_SENSOR_LOCATION_REAR_DROPOUT = 10, /**<-- Rear Dropout */ - BLE_SENSOR_LOCATION_CHAINSTAY = 11, /**<-- Chainstay */ - BLE_SENSOR_LOCATION_REAR_WHEEL = 12, /**<-- Rear Wheel */ - BLE_SENSOR_LOCATION_REAR_HUB = 13, /**<-- Rear Hub */ -}ble_sensor_location_t; - -#define BLE_NB_MAX_SENSOR_LOCATIONS 14 - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_SENSOR_LOCATION_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c deleted file mode 100644 index db90cc0693..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.c +++ /dev/null @@ -1,237 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/* Attention! - * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile - * qualification listings, this section of source code must not be modified. - */ - -#include "ble_srv_common.h" -#include -#include "nordic_common.h" -#include "app_error.h" -#include "nrf_ble.h" - -bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data) -{ - uint16_t cccd_value = uint16_decode(p_encoded_data); - return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); -} - -bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data) -{ - uint16_t cccd_value = uint16_decode(p_encoded_data); - return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0); -} - -uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, - const ble_srv_report_ref_t * p_report_ref) -{ - uint8_t len = 0; - - p_encoded_buffer[len++] = p_report_ref->report_id; - p_encoded_buffer[len++] = p_report_ref->report_type; - - APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN); - return len; -} - - -void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii) -{ - p_utf8->length = (uint16_t)strlen(p_ascii); - p_utf8->p_str = (uint8_t *)p_ascii; -} - - -/**@brief Function for setting security requirements of a characteristic. - * - * @param[in] level required security level. - * @param[out] p_perm Characteristic security requirements. - * - * @return encoded security level and security mode. - */ -static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm) -{ - - - BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); - switch (level) - { - case SEC_NO_ACCESS: - BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm); - break; - case SEC_OPEN: - BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm); - break; - case SEC_JUST_WORKS: - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm); - break; - case SEC_MITM: - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm); - break; - case SEC_SIGNED: - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm); - break; - case SEC_SIGNED_MITM: - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm); - break; - } - return; -} - - -uint32_t characteristic_add(uint16_t service_handle, - ble_add_char_params_t * p_char_props, - ble_gatts_char_handles_t * p_char_handle) -{ - ble_gatts_char_md_t char_md; - ble_gatts_attr_t attr_char_value; - ble_uuid_t char_uuid; - ble_gatts_attr_md_t attr_md; - ble_gatts_attr_md_t user_descr_attr_md; - ble_gatts_attr_md_t cccd_md; - - if (p_char_props->uuid_type == 0) - { - char_uuid.type = BLE_UUID_TYPE_BLE; - } - else - { - char_uuid.type = p_char_props->uuid_type; - } - char_uuid.uuid = p_char_props->uuid; - - memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t)); - set_security_req(p_char_props->read_access, &attr_md.read_perm); - set_security_req(p_char_props->write_access, & attr_md.write_perm); - attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0); - attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0); - attr_md.vlen = (p_char_props->is_var_len ? 1 : 0); - attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - - - memset(&char_md, 0, sizeof(ble_gatts_char_md_t)); - if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1)) - { - - memset(&cccd_md, 0, sizeof(cccd_md)); - set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - - cccd_md.vloc = BLE_GATTS_VLOC_STACK; - - char_md.p_cccd_md = &cccd_md; - } - char_md.char_props = p_char_props->char_props; - char_md.char_ext_props = p_char_props->char_ext_props; - - memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t)); - attr_char_value.p_uuid = &char_uuid; - attr_char_value.p_attr_md = &attr_md; - attr_char_value.max_len = p_char_props->max_len; - if (p_char_props->p_init_value != NULL) - { - attr_char_value.init_len = p_char_props->init_len; - attr_char_value.p_value = p_char_props->p_init_value; - } - if (p_char_props->p_user_descr != NULL) - { - memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t)); - char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size; - char_md.char_user_desc_size = p_char_props->p_user_descr->size; - char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc; - - char_md.p_user_desc_md = &user_descr_attr_md; - - set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm); - set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm); - - user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0); - user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0); - user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0); - user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - } - if (p_char_props->p_presentation_format != NULL) - { - char_md.p_char_pf = p_char_props->p_presentation_format; - } - return sd_ble_gatts_characteristic_add(service_handle, - &char_md, - &attr_char_value, - p_char_handle); -} - - -uint32_t descriptor_add(uint16_t char_handle, - ble_add_descr_params_t * p_descr_props, - uint16_t * p_descr_handle) -{ - ble_gatts_attr_t descr_params; - ble_uuid_t desc_uuid; - ble_gatts_attr_md_t attr_md; - - memset(&descr_params, 0, sizeof(descr_params)); - if (p_descr_props->uuid_type == 0) - { - desc_uuid.type = BLE_UUID_TYPE_BLE; - } - else - { - desc_uuid.type = p_descr_props->uuid_type; - } - desc_uuid.uuid = p_descr_props->uuid; - descr_params.p_uuid = &desc_uuid; - - set_security_req(p_descr_props->read_access, &attr_md.read_perm); - set_security_req(p_descr_props->write_access,&attr_md.write_perm); - - attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0); - attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0); - attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0); - attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK); - descr_params.p_attr_md = &attr_md; - - descr_params.init_len = p_descr_props->init_len; - descr_params.init_offs = p_descr_props->init_offs; - descr_params.max_len = p_descr_props->max_len; - descr_params.p_value = p_descr_props->p_value; - - return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle); -} diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h deleted file mode 100644 index a63ed2d41b..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/common/ble_srv_common.h +++ /dev/null @@ -1,409 +0,0 @@ -/** - * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup ble_sdk_srv_common Common service definitions - * @{ - * @ingroup ble_sdk_srv - * @brief Constants, type definitions, and functions that are common to all services. - */ - -#ifndef BLE_SRV_COMMON_H__ -#define BLE_SRV_COMMON_H__ - -#include -#include -#include "ble_types.h" -#include "app_util.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_gatt.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** @defgroup UUID_SERVICES Service UUID definitions - * @{ */ -#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */ -#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */ -#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */ -#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */ -#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */ -#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */ -#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */ -#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */ -#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */ -#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */ -#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */ -#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */ -#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */ -#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */ -#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */ -#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */ -#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */ -#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */ -#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */ -#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/ -#define BLE_UUID_CGM_SERVICE 0x181F /**< Continuous Glucose Monitoring service UUID*/ -#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/ -#define BLE_UUID_OTS_SERVICE 0x1825 /**< Object Transfer Service UUID*/ - -/** @} */ - -/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions - * @{ */ -#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */ -#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */ -#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */ -#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */ -#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */ -#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */ -#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */ -#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */ -#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */ -#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */ -#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */ -#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */ -#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */ -#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */ -#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */ -#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */ -#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */ -#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */ -#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */ -#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */ -#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */ -#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */ -#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */ -#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */ -#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */ -#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */ -#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */ -#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */ -#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */ -#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */ -#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */ -#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */ -#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */ -#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */ -#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */ -#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */ -#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */ -#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */ -#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */ -#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */ -#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */ -#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */ -#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */ -#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */ -#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */ -#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */ -#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */ -#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */ -#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */ -#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */ -#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */ -#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */ -#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */ -#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */ -#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */ -#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */ -#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */ -#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */ -#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */ -#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */ -#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */ -#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */ -#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */ -#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */ -#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */ -#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */ -#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */ -#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */ -#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */ -#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */ -#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */ -#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */ -#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */ -#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */ -#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */ -#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */ -#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/ -#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/ -#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/ -#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/ -#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/ -#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/ -#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/ -#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/ -#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/ -#define BLE_UUID_OTS_FEATURES 0x2ABD /**< OTS Service, feature characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_NAME 0x2ABE /**< OTS Service, Object Name characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_TYPE 0x2ABF /**< OTS Service, Object Type characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_SIZE 0x2AC0 /**< OTS Service, Object Size characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_FIRST_CREATED 0x2AC1 /**< OTS Service, Object First Created characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_LAST_MODIFIED 0x2AC2 /**< OTS Service, Object Last Modified characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_ID 0x2AC3 /**< OTS Service, Object ID characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_PROPERTIES 0x2AC4 /**< OTS Service, Object Properties characteristic UUID*/ -#define BLE_UUID_OTS_OACP 0x2AC5 /**< OTS Service, Object Action Control Point characteristic UUID*/ -#define BLE_UUID_OTS_OLCP 0x2AC6 /**< OTS Service, Object List Control Point characteristic UUID*/ -#define BLE_UUID_OTS_LF 0x2AC7 /**< OTS Service, Object List Filter characteristic UUID*/ -#define BLE_UUID_OTS_OBJECT_CHANGED 0x2AC8 /**< OTS Service, Object Changed characteristic UUID*/ - - - - -/** @} */ - -/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values - * @{ */ -#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */ -#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */ -#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */ -/** @} */ - -#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */ -#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */ - -/**@brief Type definition for error handler function that will be called in case of an error in - * a service or a service library module. */ -typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error); - - - -/**@brief Value of a Report Reference descriptor. - * - * @details This is mapping information that maps the parent characteristic to the Report ID(s) and - * Report Type(s) defined within a Report Map characteristic. - */ -typedef struct -{ - uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */ - uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */ -} ble_srv_report_ref_t; - -/**@brief UTF-8 string data type. - * - * @note The type can only hold a pointer to the string data (i.e. not the actual data). - */ -typedef struct -{ - uint16_t length; /**< String length. */ - uint8_t * p_str; /**< String data. */ -} ble_srv_utf8_str_t; - - -/**@brief Security settings structure. - * @details This structure contains the security options needed during initialization of the - * service. - */ -typedef struct -{ - ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ - ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ -} ble_srv_security_mode_t; - -/**@brief Security settings structure. - * @details This structure contains the security options needed during initialization of the - * service. It can be used when the characteristics contains a CCCD. - */ -typedef struct -{ - ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */ - ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */ - ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */ -} ble_srv_cccd_security_mode_t; - -/**@brief Function for decoding a CCCD value, and then testing if notification is - * enabled. - * - * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. - * - * @retval TRUE If notification is enabled. - * @retval FALSE Otherwise. - */ -bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data); - - -/**@brief Function for decoding a CCCD value, and then testing if indication is - * enabled. - * - * @param[in] p_encoded_data Buffer where the encoded CCCD is stored. - * - * @retval TRUE If indication is enabled. - * @retval FALSE Otherwise. - */ -bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data); - - -/**@brief Function for encoding a Report Reference Descriptor. - * - * @param[in] p_encoded_buffer The buffer of the encoded data. - * @param[in] p_report_ref Report Reference value to be encoded. - * - * @return Length of the encoded data. - */ -uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer, - const ble_srv_report_ref_t * p_report_ref); - -/**@brief Function for making a UTF-8 structure refer to an ASCII string. - * - * @param[out] p_utf8 UTF-8 structure to be set. - * @param[in] p_ascii ASCII string to be referred to. - */ -void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii); - - -/**@brief Security Access enumeration. - * @details This enumeration gives the possible requirements for accessing a characteristic value. - */ -typedef enum -{ - SEC_NO_ACCESS = 0, /**< Not possible to access. */ - SEC_OPEN = 1, /**< Access open. */ - SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */ - SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */ - SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */ - SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */ -}security_req_t; - - -/**@brief Characteristic User Descriptor parameters. - * @details This structure contains the parameters for User Descriptor. - */ -typedef struct -{ - uint16_t max_size; /**< Maximum size of the user descriptor*/ - uint16_t size; /**< Size of the user descriptor*/ - uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/ - bool is_var_len; /**< Indicates if the user descriptor has variable length.*/ - ble_gatt_char_props_t char_props; /**< user descriptor properties.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - security_req_t read_access; /**< Security requirement for reading the user descriptor.*/ - security_req_t write_access; /**< Security requirement for writing the user descriptor.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ -}ble_add_char_user_desc_t; - - -/**@brief Add characteristic parameters structure. - * @details This structure contains the parameters needed to use the @ref characteristic_add function. - */ -typedef struct -{ - uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/ - uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ - uint16_t max_len; /**< Maximum length of the characteristic value.*/ - uint16_t init_len; /**< Initial length of the characteristic value.*/ - uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/ - bool is_var_len; /**< Indicates if the characteristic value has variable length.*/ - ble_gatt_char_props_t char_props; /**< Characteristic properties.*/ - ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic extended properties.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - security_req_t read_access; /**< Security requirement for reading the characteristic value.*/ - security_req_t write_access; /**< Security requirement for writing the characteristic value.*/ - security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ - ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/ - ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/ -} ble_add_char_params_t; - - -/**@brief Add descriptor parameters structure. - * @details This structure contains the parameters needed to use the @ref descriptor_add function. - */ -typedef struct -{ - uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/ - uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/ - bool is_defered_read; /**< Indicate if deferred read operations are supported.*/ - bool is_defered_write; /**< Indicate if deferred write operations are supported.*/ - bool is_var_len; /**< Indicates if the descriptor value has variable length.*/ - security_req_t read_access; /**< Security requirement for reading the descriptor value.*/ - security_req_t write_access; /**< Security requirement for writing the descriptor value.*/ - bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/ - uint16_t init_len; /**< Initial descriptor value length in bytes. */ - uint16_t init_offs; /**< Initial descriptor value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */ - uint16_t max_len; /**< Maximum descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */ - uint8_t* p_value; /**< Pointer to the value of the descriptor*/ -} ble_add_descr_params_t; - - -/**@brief Function for adding a characteristic to a given service. - * - * If no pointer is given for the initial value, - * the initial length parameter will be ignored and the initial length will be 0. - * - * @param[in] service_handle Handle of the service to which the characteristic is to be added. - * @param[in] p_char_props Information needed to add the characteristic. - * @param[out] p_char_handle Handle of the added characteristic. - * - * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. - */ -uint32_t characteristic_add(uint16_t service_handle, - ble_add_char_params_t * p_char_props, - ble_gatts_char_handles_t * p_char_handle); - - -/**@brief Function for adding a characteristic's descriptor to a given characteristic. - * - * @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially. - * @param[in] p_descr_props Information needed to add the descriptor. - * @param[out] p_descr_handle Handle of the added descriptor. - * - * @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned. - */ -uint32_t descriptor_add(uint16_t char_handle, - ble_add_descr_params_t * p_descr_props, - uint16_t * p_descr_handle); - - - -#ifdef __cplusplus -} -#endif - -#endif // BLE_SRV_COMMON_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c deleted file mode 100644 index baa42956fa..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.c +++ /dev/null @@ -1,552 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_GATT) - -#include "nrf_ble_gatt.h" - -#define NRF_LOG_MODULE_NAME ble_gatt -#include "nrf_log.h" -NRF_LOG_MODULE_REGISTER(); - - -#define L2CAP_HDR_LEN 4 //!< Length of a L2CAP header, in bytes. - - -STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE <= 251); -STATIC_ASSERT(NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN <= 255); - - -/**@brief Initialize a link's parameters to defaults. */ -static void link_init(nrf_ble_gatt_link_t * p_link) -{ - p_link->att_mtu_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_link->att_mtu_effective = BLE_GATT_ATT_MTU_DEFAULT; - p_link->att_mtu_exchange_pending = false; - p_link->att_mtu_exchange_requested = false; -#if !defined (S112) - p_link->data_length_desired = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; - p_link->data_length_effective = BLE_GATT_ATT_MTU_DEFAULT + L2CAP_HDR_LEN; -#endif // !defined (S112) -} - -/**@brief Start a data length update request. - * @details This function is called to request a data length update upon connection. - * When the peer requests a data length update, sd_ble_gap_data_length_update() - * is called directly in response to the BLE_GAP_EVT_DATA_LENGTH_UPDATE event in - * on_data_length_update_evt(). - */ -#if !defined (S112) -static void data_length_update(uint16_t conn_handle, nrf_ble_gatt_t const * p_gatt) -{ - NRF_LOG_DEBUG("Requesting to update data length to %u on connection 0x%x.", - p_gatt->links[conn_handle].data_length_desired, conn_handle); - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = p_gatt->links[conn_handle].data_length_desired, - .max_tx_octets = p_gatt->links[conn_handle].data_length_desired, - .max_rx_time_us = BLE_GAP_DATA_LENGTH_AUTO, - .max_tx_time_us = BLE_GAP_DATA_LENGTH_AUTO, - }; - - ret_code_t err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gap_data_length_update() (request)" - " on connection 0x%x returned unexpected value 0x%x.", - conn_handle, err_code); - } -} -#endif // !defined (S112) - - -/**@brief Handle a connected event. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_connected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - // Update the link desired settings to reflect the current global settings. -#if !defined (S112) - p_link->data_length_desired = p_gatt->data_length; -#endif // !defined (S112) - switch (p_ble_evt->evt.gap_evt.params.connected.role) - { - case BLE_GAP_ROLE_PERIPH: - p_link->att_mtu_desired = p_gatt->att_mtu_desired_periph; - break; -#if !defined (S112) - case BLE_GAP_ROLE_CENTRAL: - p_link->att_mtu_desired = p_gatt->att_mtu_desired_central; - break; -#endif // !defined (S112) - default: - // Ignore. - break; - } - - // Begin an ATT MTU exchange if necessary. - if (p_link->att_mtu_desired > p_link->att_mtu_effective) - { - NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x.", - p_link->att_mtu_desired, conn_handle); - - err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, p_link->att_mtu_desired); - - if (err_code == NRF_SUCCESS) - { - p_link->att_mtu_exchange_requested = true; - } - else if (err_code == NRF_ERROR_BUSY) - { - p_link->att_mtu_exchange_pending = true; - NRF_LOG_DEBUG("sd_ble_gattc_exchange_mtu_request()" - " on connection 0x%x returned busy, will retry.", conn_handle); - } - else - { - NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request()" - " returned unexpected value 0x%x.", - err_code); - } - } - -#if !defined (S112) - // Send a data length update request if necessary. - if (p_link->data_length_desired > p_link->data_length_effective) - { - data_length_update(conn_handle, p_gatt); - } -#endif // !defined (S112) -} - - -static void on_disconnected_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - // Reset connection parameters. - link_init(&p_gatt->links[p_ble_evt->evt.gap_evt.conn_handle]); -} - - -/**@brief Handle a BLE_GATTC_EVT_EXCHANGE_MTU_RSP event. - * - * @details The effective ATT MTU is set to the lowest between what we requested and the peer's - * response. This events concludes the ATT MTU exchange. An event is sent to the user - * and a data length update procedure is started if necessary. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_exchange_mtu_rsp_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle; - uint16_t server_rx_mtu = p_ble_evt->evt.gattc_evt.params.exchange_mtu_rsp.server_rx_mtu; - - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - // Determine the lowest MTU between our own desired MTU and the peer's. - // The MTU may not be less than BLE_GATT_ATT_MTU_DEFAULT. - p_link->att_mtu_effective = MIN(server_rx_mtu, p_link->att_mtu_desired); - p_link->att_mtu_effective = MAX(p_link->att_mtu_effective, BLE_GATT_ATT_MTU_DEFAULT); - - NRF_LOG_DEBUG("ATT MTU updated to %u bytes on connection 0x%x (response).", - p_link->att_mtu_effective, conn_handle); - - // Trigger an event indicating that the ATT MTU size has changed. - // Send an event to the application only if an ATT MTU exchange was requested. - if ((p_gatt->evt_handler != NULL) && (p_link->att_mtu_exchange_requested)) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, - .conn_handle = conn_handle, - .params.att_mtu_effective = p_link->att_mtu_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } - - p_link->att_mtu_exchange_requested = false; - p_link->att_mtu_exchange_pending = false; -} - - -/**@brief Handle a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -static void on_exchange_mtu_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; - uint16_t client_mtu = p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu; - - nrf_ble_gatt_link_t * p_link = &p_gatt->links[conn_handle]; - - NRF_LOG_DEBUG("Peer on connection 0x%x requested an ATT MTU of %u bytes.", - conn_handle, client_mtu); - - client_mtu = MAX(client_mtu, BLE_GATT_ATT_MTU_DEFAULT); - p_link->att_mtu_effective = MIN(client_mtu, p_link->att_mtu_desired); - p_link->att_mtu_exchange_pending = false; - - NRF_LOG_DEBUG("Updating ATT MTU to %u bytes (desired: %u) on connection 0x%x.", - p_link->att_mtu_effective, p_link->att_mtu_desired, conn_handle); - - err_code = sd_ble_gatts_exchange_mtu_reply(conn_handle, p_link->att_mtu_desired); - - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gatts_exchange_mtu_reply() returned unexpected value 0x%x.", - err_code); - } - - // If an ATT_MTU exchange was requested to the peer, defer sending - // the data length update request and the event to the application until - // the response for that request is received. - if (p_link->att_mtu_exchange_requested) - { - return; - } - - // The ATT MTU exchange has finished. Send an event to the application. - if (p_gatt->evt_handler != NULL) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_ATT_MTU_UPDATED, - .conn_handle = conn_handle, - .params.att_mtu_effective = p_link->att_mtu_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } -} - - -/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE event. - * - * @details Update the connection data length and send an event to the user. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -#if !defined (S112) -static void on_data_length_update_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ble_gap_evt_t const gap_evt = p_ble_evt->evt.gap_evt; - uint16_t const conn_handle = gap_evt.conn_handle; - - // Update the connection data length. - p_gatt->links[conn_handle].data_length_effective = - gap_evt.params.data_length_update.effective_params.max_tx_octets; - - NRF_LOG_DEBUG("Data length updated to %u on connection 0x%0x.", - p_gatt->links[conn_handle].data_length_effective, - conn_handle); - - NRF_LOG_DEBUG("max_rx_octets: %u", - gap_evt.params.data_length_update.effective_params.max_rx_octets); - NRF_LOG_DEBUG("max_tx_octets: %u", - gap_evt.params.data_length_update.effective_params.max_tx_octets); - NRF_LOG_DEBUG("max_rx_time: %u", - gap_evt.params.data_length_update.effective_params.max_rx_time_us); - NRF_LOG_DEBUG("max_tx_time: %u", - gap_evt.params.data_length_update.effective_params.max_tx_time_us); - - if (p_gatt->evt_handler != NULL) - { - nrf_ble_gatt_evt_t const evt = - { - .evt_id = NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED, - .conn_handle = conn_handle, - .params.data_length = p_gatt->links[conn_handle].data_length_effective, - }; - - p_gatt->evt_handler(p_gatt, &evt); - } -} -#endif // !defined (S112) - - -/**@brief Handle a BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST event. - * - *@details Reply with a sd_ble_gap_data_length_update() call, using the minimum between the - * link's preferred data length, and what requested by the peer. - * The link preferred data length is set to the global preferred data length - * upon connection and can be overridden by calling nrf_ble_gatt_data_length_set(). - * The default is NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN. - * - *@note The SoftDevice will not send any BLE_GAP_EVT_DATA_LENGTH_UPDATE events on this side. - * Therefore, the connection data length is updated immediately and an event is sent - * to the user. - * - * @param[in] p_gatt GATT structure. - * @param[in] p_ble_evt Event received from the BLE stack. - */ -#if !defined (S112) -static void on_data_length_update_request_evt(nrf_ble_gatt_t * p_gatt, ble_evt_t const * p_ble_evt) -{ - ret_code_t err_code; - - ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; - nrf_ble_gatt_link_t * p_link = &p_gatt->links[p_gap_evt->conn_handle]; - - uint8_t const data_length_peer = - p_gap_evt->params.data_length_update_request.peer_params.max_tx_octets; - - NRF_LOG_DEBUG("Peer on connection 0x%x requested a data length of %u bytes.", - p_gap_evt->conn_handle, data_length_peer); - - uint8_t const data_length = MIN(p_link->data_length_desired, data_length_peer); - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = data_length, - .max_tx_octets = data_length, - }; - - NRF_LOG_DEBUG("Updating data length to %u bytes on connection 0x%x.", - data_length, p_gap_evt->conn_handle); - - err_code = sd_ble_gap_data_length_update(p_gap_evt->conn_handle, &dlp, NULL); - - if (err_code != NRF_SUCCESS) - { - NRF_LOG_ERROR("sd_ble_gap_data_length_update() (reply)" - " returned unexpected value 0x%x.", - err_code); - } -} -#endif // !defined (S112) - - -ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - p_gatt->evt_handler = evt_handler; - p_gatt->att_mtu_desired_periph = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE; - p_gatt->data_length = NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN; - - for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++) - { - link_init(&p_gatt->links[i]); - } - - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->att_mtu_desired_periph = desired_mtu; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu) -{ - VERIFY_PARAM_NOT_NULL(p_gatt); - - if ((desired_mtu < BLE_GATT_ATT_MTU_DEFAULT) || (desired_mtu > NRF_SDH_BLE_GATT_MAX_MTU_SIZE)) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->att_mtu_desired_central = desired_mtu; - return NRF_SUCCESS; -} - - -uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle) -{ - if ((p_gatt == NULL) || (conn_handle >= NRF_BLE_GATT_LINK_COUNT)) - { - return 0; - } - - return p_gatt->links[conn_handle].att_mtu_effective; -} - -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, - uint16_t conn_handle, - uint8_t data_length) -{ - ret_code_t err_code; - - if (p_gatt == NULL) - { - return NRF_ERROR_NULL; - } - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - p_gatt->data_length = MIN(data_length, NRF_SDH_BLE_GATT_MAX_MTU_SIZE + L2CAP_HDR_LEN); - return NRF_SUCCESS; - } - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_gatt->links[conn_handle].data_length_desired = data_length; - - ble_gap_data_length_params_t const dlp = - { - .max_rx_octets = data_length, - .max_tx_octets = data_length, - }; - - err_code = sd_ble_gap_data_length_update(conn_handle, &dlp, NULL); - return err_code; -} -#endif // !defined (S112) - - -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, - uint16_t conn_handle, - uint8_t * p_data_length) -{ - if ((p_gatt == NULL) || (p_data_length == NULL)) - { - return NRF_ERROR_NULL; - } - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - *p_data_length = p_gatt->data_length; - return NRF_SUCCESS; - } - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return NRF_ERROR_INVALID_PARAM; - } - - *p_data_length = p_gatt->links[conn_handle].data_length_effective; - return NRF_SUCCESS; -} -#endif // !defined (S112) - - -void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - nrf_ble_gatt_t * p_gatt = (nrf_ble_gatt_t *)p_context; - uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; - - if (conn_handle >= NRF_BLE_GATT_LINK_COUNT) - { - return; - } - - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_CONNECTED: - on_connected_evt(p_gatt, p_ble_evt); - break; - - case BLE_GAP_EVT_DISCONNECTED: - on_disconnected_evt(p_gatt, p_ble_evt); - break; - - case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: - on_exchange_mtu_rsp_evt(p_gatt, p_ble_evt); - break; - - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - on_exchange_mtu_request_evt(p_gatt, p_ble_evt); - break; -#if !defined (S112) - case BLE_GAP_EVT_DATA_LENGTH_UPDATE: - on_data_length_update_evt(p_gatt, p_ble_evt); - break; - - case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: - on_data_length_update_request_evt(p_gatt, p_ble_evt); - break; -#endif // !defined (S112) - default: - break; - } - - if (p_gatt->links[conn_handle].att_mtu_exchange_pending) - { - ret_code_t err_code; - - err_code = sd_ble_gattc_exchange_mtu_request(conn_handle, - p_gatt->links[conn_handle].att_mtu_desired); - - if (err_code == NRF_SUCCESS) - { - p_gatt->links[conn_handle].att_mtu_exchange_pending = false; - p_gatt->links[conn_handle].att_mtu_exchange_requested = true; - - NRF_LOG_DEBUG("Requesting to update ATT MTU to %u bytes on connection 0x%x (retry).", - p_gatt->links[conn_handle].att_mtu_desired, conn_handle); - } - else if (err_code != NRF_ERROR_BUSY) - { - NRF_LOG_ERROR("sd_ble_gattc_exchange_mtu_request() returned unexpected value 0x%x.", - err_code); - } - } -} - -#endif //NRF_BLE_GATT_ENABLED diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h deleted file mode 100644 index 300efeb9ee..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_gatt/nrf_ble_gatt.h +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup nrf_ble_gatt GATT module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for negotiating and keeping track of GATT connection parameters and updating the data length. - */ - -#ifndef NRF_BLE_GATT_H__ -#define NRF_BLE_GATT_H__ - -#include -#include -#include -#include "nrf_ble.h" -#include "ble_gatt.h" -#include "sdk_config.h" -#include "sdk_errors.h" -#include "app_util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/**@brief Macro for defining a nrf_ble_gatt instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define NRF_BLE_GATT_DEF(_name) \ -static nrf_ble_gatt_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - NRF_BLE_GATT_BLE_OBSERVER_PRIO, \ - nrf_ble_gatt_on_ble_evt, &_name) - -/**@brief The maximum number of peripheral and central connections combined. - * This value is based on what is configured in the SoftDevice handler sdk_config. - */ -#define NRF_BLE_GATT_LINK_COUNT (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT) - - -/**@brief GATT module event types. */ -typedef enum -{ - NRF_BLE_GATT_EVT_ATT_MTU_UPDATED = 0xA77, //!< The ATT_MTU size was updated. - NRF_BLE_GATT_EVT_DATA_LENGTH_UPDATED = 0xDA7A, //!< The data length was updated. -} nrf_ble_gatt_evt_id_t; - -/**@brief GATT module event. */ -typedef struct -{ - nrf_ble_gatt_evt_id_t evt_id; //!< Event ID. - uint16_t conn_handle; //!< Connection handle on which the event happened. - union - { - uint16_t att_mtu_effective; //!< Effective ATT_MTU. -#if !defined (S112) - uint8_t data_length; //!< Data length value. -#endif // !defined (S112) - } params; -} nrf_ble_gatt_evt_t; - -// Forward declaration of the nrf_ble_gatt_t type. -typedef struct nrf_ble_gatt_s nrf_ble_gatt_t; - -/**@brief GATT module event handler type. - * - * The GATT module calls a function of this type when a parameter value is changed. - */ -typedef void (*nrf_ble_gatt_evt_handler_t) (nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt); - -/**@brief GATT information for each connection. */ -typedef struct -{ - uint16_t att_mtu_desired; //!< Requested ATT_MTU size (in bytes). - uint16_t att_mtu_effective; //!< Effective ATT_MTU size (in bytes). - bool att_mtu_exchange_pending; //!< Indicates that an ATT_MTU exchange request is pending (the call to @ref sd_ble_gattc_exchange_mtu_request returned @ref NRF_ERROR_BUSY). - bool att_mtu_exchange_requested; //!< Indicates that an ATT_MTU exchange request was made. -#if !defined (S112) - uint8_t data_length_desired; //!< Desired data length (in bytes). - uint8_t data_length_effective; //!< Requested data length (in bytes). -#endif // !defined (S112) -} nrf_ble_gatt_link_t; - - -/**@brief GATT structure that contains status information for the GATT module. */ -struct nrf_ble_gatt_s -{ - uint16_t att_mtu_desired_periph; //!< Requested ATT_MTU size for the next peripheral connection that is established. - uint16_t att_mtu_desired_central; //!< Requested ATT_MTU size for the next central connection that is established. - uint8_t data_length; //!< Data length to use for the next connection that is established. - nrf_ble_gatt_link_t links[NRF_BLE_GATT_LINK_COUNT]; //!< GATT related information for all active connections. - nrf_ble_gatt_evt_handler_t evt_handler; //!< GATT event handler. -}; - - -/**@brief Function for initializing the GATT module. - * - * @param[in] evt_handler Event handler. - * @param[out] p_gatt Pointer to the GATT structure. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - */ -ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler); - - -/**@brief Function for setting the ATT_MTU size for the next connection that is established as peripheral. - * - * @param[in] p_gatt Pointer to the GATT structure. - * @param[in] desired_mtu Requested ATT_MTU size. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than - * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller than - * @ref BLE_GATT_ATT_MTU_DEFAULT. - */ -ret_code_t nrf_ble_gatt_att_mtu_periph_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); - - -/**@brief Function for setting the ATT_MTU size for the next connection that is established as central. - * - * @param[in,out] p_gatt Pointer to the GATT structure. - * @param[in] desired_mtu Requested ATT_MTU size. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the size of @p desired_mtu is bigger than - * @ref NRF_SDH_BLE_GATT_MAX_MTU_SIZE or smaller - * than @ref BLE_GATT_ATT_MTU_DEFAULT. - */ -ret_code_t nrf_ble_gatt_att_mtu_central_set(nrf_ble_gatt_t * p_gatt, uint16_t desired_mtu); - - -/**@brief Function for setting the data length for a connection. - * - * @details If @p conn_handle is a handle to an existing connection, a data length update - * request is sent on that connection. - * If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, a data length update request - * is sent on the next connection that is established after the ATT_MTU - * exchange has completed. If no ATT_MTU exchange procedure is carried - * out (for example, if a default ATT_MTU size is used), the data length - * is not changed. - */ -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_set(nrf_ble_gatt_t * p_gatt, - uint16_t conn_handle, - uint8_t data_length); -#endif // !defined (S112) - -/**@brief Function for retrieving the data length of a connection. - * - * @details If @p conn_handle is @ref BLE_CONN_HANDLE_INVALID, the function retrieves the data - * length that will be requested for the next connection. - * If @p conn_handle is a handle to an existing connection, the function retrieves - * the effective data length that was negotiated for that connection. - * - * @param[in,out] p_gatt Pointer to the GATT structure. - * @param[in] conn_handle The connection for which to retrieve the data length, or - * @ref BLE_CONN_HANDLE_INVALID to retrieve the requested data length - * for the next connection. - * @param[out] p_data_length The connection data length. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_NULL If @p p_gatt or @p p_data_length is NULL. - * @retval NRF_ERROR_INVALID_PARAM If @p conn_handle is larger than @ref NRF_BLE_GATT_LINK_COUNT. - */ -#if !defined (S112) -ret_code_t nrf_ble_gatt_data_length_get(nrf_ble_gatt_t const * p_gatt, - uint16_t conn_handle, - uint8_t * p_data_length); -#endif // !defined (S112) - -/**@brief Function for handling BLE stack events. - * - * @details This function handles events from the BLE stack that are of interest to the module. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Pointer to the GATT structure. - */ -void nrf_ble_gatt_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); - - -/**@brief Function for getting the current ATT_MTU size for a given connection. - * - * @param[in] p_gatt Pointer to the GATT structure. - * @param[in] conn_handle Connection handle of the connection. - * - * @return ATT_MTU size for the given connection. - * @retval 0 If @p p_gatt is NULL or if @p conn_handle is larger than - * the supported maximum number of connections. - */ -uint16_t nrf_ble_gatt_eff_mtu_get(nrf_ble_gatt_t const * p_gatt, uint16_t conn_handle); - - -#ifdef __cplusplus -} -#endif - -#endif // NRF_BLE_GATT_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c deleted file mode 100644 index cafd24eca2..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.c +++ /dev/null @@ -1,447 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(NRF_BLE_QWR) -#include -#include "nrf_ble_qwr.h" -#include "nrf_ble.h" -#include "ble_srv_common.h" - - -#define NRF_BLE_QWR_INITIALIZED 0xDE // Non-zero value used to make sure the given structure has been initialized by the module. -#define MODULE_INITIALIZED (p_qwr->initialized == NRF_BLE_QWR_INITIALIZED) -#include "sdk_macros.h" - -ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_init_t const * p_qwr_init) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_PARAM_NOT_NULL(p_qwr_init); - if (MODULE_INITIALIZED) - { - return NRF_ERROR_INVALID_STATE; - } - - memset(p_qwr->attr_handles, 0, sizeof(p_qwr->attr_handles)); - p_qwr->nb_registered_attr = 0; - p_qwr->error_handler = p_qwr_init->error_handler; - p_qwr->is_user_mem_reply_pending = false; - p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; - p_qwr->initialized = NRF_BLE_QWR_INITIALIZED; - p_qwr->mem_buffer = p_qwr_init->mem_buffer; - p_qwr->callback = p_qwr_init->callback; - p_qwr->nb_written_handles = 0; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_MODULE_INITIALIZED(); - - if (p_qwr->nb_registered_attr == NRF_BLE_QWR_ATTR_LIST_SIZE) - { - return (NRF_ERROR_NO_MEM); - } - - if (attr_handle == BLE_GATT_HANDLE_INVALID) - { - return NRF_ERROR_INVALID_PARAM; - } - - p_qwr->attr_handles[p_qwr->nb_registered_attr] = attr_handle; - p_qwr->nb_registered_attr++; - - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, - uint16_t attr_handle, - uint8_t * p_mem, - uint16_t * p_len) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_PARAM_NOT_NULL(p_mem); - VERIFY_PARAM_NOT_NULL(p_len); - VERIFY_MODULE_INITIALIZED(); - - uint16_t i = 0; - uint16_t handle = BLE_GATT_HANDLE_INVALID; - uint16_t val_len = 0; - uint16_t val_offset = 0; - uint16_t cur_len = 0; - - do - { - handle = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - - if (handle == BLE_GATT_HANDLE_INVALID) - { - break; - } - - i += sizeof(uint16_t); - val_offset = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - i += sizeof(uint16_t); - val_len = uint16_decode(&(p_qwr->mem_buffer.p_mem[i])); - i += sizeof(uint16_t); - - if (handle == attr_handle) - { - cur_len = val_offset + val_len; - if (cur_len <= *p_len) - { - memcpy((p_mem + val_offset), &(p_qwr->mem_buffer.p_mem[i]), val_len); - } - else - { - return NRF_ERROR_NO_MEM; - } - } - - i += val_len; - } - while (i < p_qwr->mem_buffer.len); - - *p_len = cur_len; - return NRF_SUCCESS; -} - - -ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, - uint16_t conn_handle) -{ - VERIFY_PARAM_NOT_NULL(p_qwr); - VERIFY_MODULE_INITIALIZED(); - p_qwr->conn_handle = conn_handle; - return NRF_SUCCESS; -} - - -/**@brief checks if a user_mem_reply is pending, if so attempts to send it. - * - * @param[in] p_qwr QWR structure. - */ -static void user_mem_reply(nrf_ble_qwr_t * p_qwr) -{ - if (p_qwr->is_user_mem_reply_pending) - { - ret_code_t err_code = sd_ble_user_mem_reply(p_qwr->conn_handle, &p_qwr->mem_buffer); - if (err_code == NRF_SUCCESS) - { - p_qwr->is_user_mem_reply_pending = false; - } - else if (err_code == NRF_ERROR_BUSY) - { - p_qwr->is_user_mem_reply_pending = true; - } - else - { - p_qwr->error_handler(err_code); - } - } -} - - -/**@brief Handle a user memory request event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_common_evt User_mem_request event to be handled. - */ -static void on_user_mem_request(nrf_ble_qwr_t * p_qwr, - ble_common_evt_t const * p_common_evt) -{ - if (p_common_evt->conn_handle == p_qwr->conn_handle) - { - if (p_common_evt->params.user_mem_request.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) - { - p_qwr->is_user_mem_reply_pending = true; - user_mem_reply(p_qwr); - } - } -} - - -/**@brief Handle a user memory release event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_common_evt User_mem_release event to be handled. - */ -static void on_user_mem_release(nrf_ble_qwr_t * p_qwr, - ble_common_evt_t const * p_common_evt) -{ - if (p_common_evt->conn_handle == p_qwr->conn_handle) - { - if (p_common_evt->params.user_mem_release.type == BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES) - { - // Cancel the current operation. - p_qwr->nb_written_handles = 0; - } - } -} - - -/**@brief Handle a prepare write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write WRITE event to be handled. - */ -static void on_prepare_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - - uint32_t i; - - for (i = 0; i < p_qwr->nb_written_handles; i++) - { - if (p_qwr->written_attr_handles[i] == p_evt_write->handle) - { - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - break; - } - } - - if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) - { - for (i = 0; i < p_qwr->nb_registered_attr; i++) - { - if (p_qwr->attr_handles[i] == p_evt_write->handle) - { - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - p_qwr->written_attr_handles[p_qwr->nb_written_handles++] = p_evt_write->handle; - break; - } - } - } - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Cancel the current operation. - p_qwr->nb_written_handles = 0; - - // Report error to application. - p_qwr->error_handler(err_code); - } - -} - - -/**@brief Handle an execute write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write EXEC WRITE event to be handled. - */ -static void on_execute_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - - if (p_qwr->nb_written_handles == 0) - { - auth_reply.params.write.gatt_status = NRF_BLE_QWR_REJ_REQUEST_ERR_CODE; - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - return; - } - - for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) - { - nrf_ble_qwr_evt_t evt; - uint16_t ret_val; - - evt.evt_type = NRF_BLE_QWR_EVT_AUTH_REQUEST; - evt.attr_handle = p_qwr->written_attr_handles[i]; - ret_val = p_qwr->callback(p_qwr, &evt); - if (ret_val != BLE_GATT_STATUS_SUCCESS) - { - auth_reply.params.write.gatt_status = ret_val; - } - } - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - - // If the execute has not been rejected by any of the registered applications, propagate execute write event to all written handles. */ - if (auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) - { - for (uint16_t i = 0; i < p_qwr->nb_written_handles; i++) - { - nrf_ble_qwr_evt_t evt; - evt.evt_type = NRF_BLE_QWR_EVT_EXECUTE_WRITE; - evt.attr_handle = p_qwr->written_attr_handles[i]; - /*lint -e534 -save "Ignoring return value of function" */ - p_qwr->callback(p_qwr, &evt); - /*lint -restore*/ - - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - } - } - p_qwr->nb_written_handles = 0; -} - - -/**@brief Handle a cancel write event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_evt_write EXEC WRITE event to be handled. - */ -static void on_cancel_write(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_write_t const * p_evt_write) -{ - uint32_t err_code; - ble_gatts_rw_authorize_reply_params_t auth_reply; - memset(&auth_reply, 0, sizeof(auth_reply)); - - auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; - auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; - - err_code = sd_ble_gatts_rw_authorize_reply(p_qwr->conn_handle, &auth_reply); - if (err_code != NRF_SUCCESS) - { - // Report error to application. - p_qwr->error_handler(err_code); - } - p_qwr->nb_written_handles = 0; -} - - -/**@brief Handle a rw_authorize_request event. - * - * @param[in] p_qwr QWR structure. - * @param[in] p_gatts_evt RW_authorize_request event to be handled. - */ -static void on_rw_authorize_request(nrf_ble_qwr_t * p_qwr, - ble_gatts_evt_t const * p_gatts_evt) -{ - if (p_gatts_evt->conn_handle != p_qwr->conn_handle) - { - return; - } - - ble_gatts_evt_rw_authorize_request_t const * p_auth_req = &p_gatts_evt->params.authorize_request; - if (p_auth_req->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE) - { - return; - } - - switch (p_auth_req->request.write.op) - { - case BLE_GATTS_OP_PREP_WRITE_REQ: - on_prepare_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_PREP_WRITE_REQ - - case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: - on_execute_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_EXEC_WRITE_REQ_NOW - - case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: - on_cancel_write(p_qwr, &p_auth_req->request.write); - break; // BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL - - default: - // No implementation needed. - break; - } -} - - -void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_context); - VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); - - nrf_ble_qwr_t * p_qwr = (nrf_ble_qwr_t *)p_context; - - VERIFY_MODULE_INITIALIZED_VOID(); - - if (p_ble_evt->evt.common_evt.conn_handle == p_qwr->conn_handle) - { - user_mem_reply(p_qwr); - } - switch (p_ble_evt->header.evt_id) - { - case BLE_EVT_USER_MEM_REQUEST: - on_user_mem_request(p_qwr, &p_ble_evt->evt.common_evt); - break; // BLE_EVT_USER_MEM_REQUEST - - case BLE_EVT_USER_MEM_RELEASE: - on_user_mem_release(p_qwr, &p_ble_evt->evt.common_evt); - break; // BLE_EVT_USER_MEM_REQUEST - - case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: - on_rw_authorize_request(p_qwr, &p_ble_evt->evt.gatts_evt); - break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST - - case BLE_GAP_EVT_DISCONNECTED: - if (p_ble_evt->evt.gap_evt.conn_handle == p_qwr->conn_handle) - { - p_qwr->conn_handle = BLE_CONN_HANDLE_INVALID; - p_qwr->nb_written_handles = 0; - } - break; // BLE_GAP_EVT_DISCONNECTED - - default: - break; - } - -} -#endif // NRF_MODULE_ENABLED(NRF_BLE_QWR) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h deleted file mode 100644 index 7453730e00..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/nrf_ble_qwr/nrf_ble_qwr.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * Copyright (c) 2016 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** @file - * - * @defgroup nrf_ble_qwr Queued Writes module - * @{ - * @ingroup ble_sdk_lib - * @brief Module for handling Queued Write operations. - * - * @details This module handles prepare write, execute write, and cancel write - * commands. It also manages memory requests related to these operations. - * - * @note The application must propagate BLE stack events to this module by calling - * @ref nrf_ble_qwr_on_ble_evt(). - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef NRF_BLE_QUEUED_WRITES_H__ -#define NRF_BLE_QUEUED_WRITES_H__ - -#include -#include "nordic_common.h" -#include "sdk_common.h" -#include "nrf_ble.h" -#include "ble_srv_common.h" - -/**@brief Macro for defining a nrf_ble_qwr instance. - * - * @param _name Name of the instance. - * @hideinitializer - */ -#define NRF_BLE_QWR_DEF(_name) \ -static nrf_ble_qwr_t _name; \ -NRF_SDH_BLE_OBSERVER(_name ## _obs, \ - NRF_BLE_QWR_BLE_OBSERVER_PRIO, \ - nrf_ble_qwr_on_ble_evt, &_name) - -#ifndef NRF_BLE_QWR_ATTR_LIST_SIZE -#define NRF_BLE_QWR_ATTR_LIST_SIZE 10 //!< Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. -#endif - -#define NRF_BLE_QWR_REJ_REQUEST_ERR_CODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 0 //!< Error code used by the module to reject prepare write requests on non-registered attributes. - - -/**@brief Queued Writes module event types. */ -typedef enum -{ - NRF_BLE_QWR_EVT_EXECUTE_WRITE, //!< Event that indicates that an execute write command was received for a registered handle and that the received data was actually written and is now ready. - NRF_BLE_QWR_EVT_AUTH_REQUEST, //!< Event that indicates that an execute write command was received for a registered handle and that the write request must now be accepted or rejected. -} nrf_ble_qwr_evt_type_t; - -/**@brief Queued Writes module events. */ -typedef struct -{ - nrf_ble_qwr_evt_type_t evt_type; //!< Type of the event. - uint16_t attr_handle; //!< Handle of the attribute to which the event relates. -} nrf_ble_qwr_evt_t; - -// Forward declaration of the nrf_ble_qwr_t type. -struct nrf_ble_qwr_t; - -/**@brief Queued Writes module event handler type. - * - * If the provided event is of type @ref NRF_BLE_QWR_EVT_AUTH_REQUEST, - * this function must accept or reject the execute write request by returning - * one of the @ref BLE_GATT_STATUS_CODES.*/ -typedef uint16_t (* nrf_ble_qwr_evt_handler_t) (struct nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_evt_t * p_evt); - -/**@brief Queued Writes structure. - * @details This structure contains status information for the Queued Writes module. */ -typedef struct nrf_ble_qwr_t -{ - uint8_t initialized; //!< Flag that indicates whether the module has been initialized. - uint16_t attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of handles for registered attributes, for which the module accepts and handles prepare write operations. - uint8_t nb_registered_attr; //!< Number of registered attributes. - uint16_t written_attr_handles[NRF_BLE_QWR_ATTR_LIST_SIZE]; //!< List of attribute handles that have been written to during the current prepare write or execute write operation. - uint8_t nb_written_handles; //!< Number of attributes that have been written to during the current prepare write or execute write operation. - ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. - ble_srv_error_handler_t error_handler; //!< Error handler. - bool is_user_mem_reply_pending; //!< Flag that indicates whether a mem_reply is pending (because a previous attempt returned busy). - uint16_t conn_handle; //!< Connection handle. - nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. -} nrf_ble_qwr_t; - -/**@brief Queued Writes init structure. - * @details This structure contains all information - * that is needed to initialize the Queued Writes module. */ -typedef struct -{ - ble_srv_error_handler_t error_handler; //!< Error handler. - ble_user_mem_block_t mem_buffer; //!< Memory buffer that is provided to the SoftDevice on an ON_USER_MEM_REQUEST event. - nrf_ble_qwr_evt_handler_t callback; //!< Event handler function that is called for events concerning the handles of all registered attributes. -} nrf_ble_qwr_init_t; - - -/**@brief Function for initializing the Queued Writes module. - * - * @details Call this function in the main entry of your application to - * initialize the Queued Writes module. It must be called only once with a - * given Queued Writes structure. - * - * @param[out] p_qwr Queued Writes structure. This structure must be - * supplied by the application. It is initialized by this function - * and is later used to identify the particular Queued Writes instance. - * @param[in] p_qwr_init Initialization structure. - * - * @retval NRF_SUCCESS If the Queued Writes module was initialized successfully. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has already been initialized. - */ -ret_code_t nrf_ble_qwr_init(nrf_ble_qwr_t * p_qwr, - nrf_ble_qwr_init_t const * p_qwr_init); - - -/**@brief Function for registering an attribute with the Queued Writes module. - * - * @details Call this function for each attribute that you want to enable for - * Queued Writes (thus a series of prepare write and execute write operations). - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] attr_handle Handle of the attribute to register. - * - * @retval NRF_SUCCESS If the registration was successful. - * @retval NRF_ERROR_NO_MEM If no more memory is available to add this registration. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_attr_register(nrf_ble_qwr_t * p_qwr, uint16_t attr_handle); - - -/**@brief Function for handling BLE stack events. - * - * @details Handles all events from the BLE stack that are of interest to the Queued Writes module. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Queued Writes structure. - */ -void nrf_ble_qwr_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); - - -/**@brief Function for retrieving the received data for a given attribute. - * - * @details Call this function after receiving an @ref NRF_BLE_QWR_EVT_AUTH_REQUEST - * event to retrieve a linear copy of the data that was received for the given attribute. - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] attr_handle Handle of the attribute. - * @param[out] p_mem Pointer to the application buffer where the received data will be copied. - * @param[in,out] p_len Input: length of the input buffer. Output: length of the received data. - * - * - * @retval NRF_SUCCESS If the data was retrieved and stored successfully. - * @retval NRF_ERROR_NO_MEM If the provided buffer was smaller than the received data. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_value_get(nrf_ble_qwr_t * p_qwr, - uint16_t attr_handle, - uint8_t * p_mem, - uint16_t * p_len); - - -/**@brief Function for assigning a connection handle to a given instance of the Queued Writes module. - * - * @details Call this function when a link with a peer has been established to - * associate this link to the instance of the module. This makes it - * possible to handle several links and associate each link to a particular - * instance of this module. - * - * @param[in] p_qwr Queued Writes structure. - * @param[in] conn_handle Connection handle to be associated with the given Queued Writes instance. - * - * @retval NRF_SUCCESS If the assignment was successful. - * @retval NRF_ERROR_NULL If any of the given pointers is NULL. - * @retval NRF_ERROR_INVALID_STATE If the given context has not been initialized. - */ -ret_code_t nrf_ble_qwr_conn_handle_assign(nrf_ble_qwr_t * p_qwr, - uint16_t conn_handle); - -#ifdef __cplusplus -} -#endif - -#endif // NRF_BLE_QUEUED_WRITES_H__ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c deleted file mode 100644 index 4d6d43111a..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.c +++ /dev/null @@ -1,568 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "gatt_cache_manager.h" - -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "id_manager.h" -#include "gatts_cache_manager.h" -#include "peer_database.h" -#include "pm_mutex.h" - - -// The number of registered event handlers. -#define GCM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - -// GATT Cache Manager event handler in Peer Manager. -extern void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt); - -// GATT Cache Manager events' handlers. -// The number of elements in this array is GCM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t m_evt_handlers[] = -{ - pm_gcm_evt_handler -}; - -static bool m_module_initialized; -static uint8_t m_db_update_in_progress_mutex; /**< Mutex indicating whether a local DB write operation is ongoing. */ -static ble_conn_state_user_flag_id_t m_flag_local_db_update_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB update procedure. */ -static ble_conn_state_user_flag_id_t m_flag_local_db_apply_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB apply procedure. */ -static ble_conn_state_user_flag_id_t m_flag_service_changed_pending; /**< Flag ID for flag collection to keep track of which connections need to be sent a service changed indication. */ -static ble_conn_state_user_flag_id_t m_flag_service_changed_sent; /**< Flag ID for flag collection to keep track of which connections have been sent a service changed indication and are waiting for a handle value confirmation. */ - - -/**@brief Function for resetting the module variable(s) of the GSCM module. - * - * @param[out] The instance to reset. - */ -static void internal_state_reset() -{ - m_module_initialized = false; -} - - -static void evt_send(pm_evt_t * p_gcm_evt) -{ - p_gcm_evt->peer_id = im_peer_id_get_by_conn_handle(p_gcm_evt->conn_handle); - - for (uint32_t i = 0; i < GCM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_gcm_evt); - } -} - - -/**@brief Function for checking a write event for whether a CCCD was written during the write - * operation. - * - * @param[in] p_write_evt The parameters of the write event. - * - * @return Whether the write was on a CCCD. - */ -static bool cccd_written(ble_gatts_evt_write_t const * p_write_evt) -{ - return ( (p_write_evt->op == BLE_GATTS_OP_WRITE_REQ) - && (p_write_evt->uuid.type == BLE_UUID_TYPE_BLE) - && (p_write_evt->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG) - ); -} - - -/**@brief Function for sending an PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .conn_handle = conn_handle, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - evt_send(&error_evt); -} - - -/**@brief Function for performing the local DB update procedure in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static void local_db_apply_in_evt(uint16_t conn_handle) -{ - bool set_procedure_as_pending = false; - ret_code_t err_code; - pm_evt_t event = - { - .conn_handle = conn_handle, - }; - - if (conn_handle == BLE_CONN_HANDLE_INVALID) - { - return; - } - - err_code = gscm_local_db_cache_apply(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLIED; - - evt_send(&event); - break; - - case NRF_ERROR_BUSY: - set_procedure_as_pending = true; - break; - - case NRF_ERROR_INVALID_DATA: - event.evt_id = PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED; - - evt_send(&event); - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - /* Do nothing */ - break; - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_apply_pending, set_procedure_as_pending); -} - - -/**@brief Function for asynchronously starting a DB update procedure. - * - * @note This procedure can only be started asynchronously. - * - * @param[in] conn_handle The connection to perform the procedure on. - * @param[in] update Whether to perform the procedure. - */ -static __INLINE void local_db_update(uint16_t conn_handle, bool update) -{ - ble_conn_state_user_flag_set(conn_handle, m_flag_local_db_update_pending, update); -} - - -/**@brief Function for performing the local DB update procedure in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static bool local_db_update_in_evt(uint16_t conn_handle) -{ - bool set_procedure_as_pending = false; - bool success = false; - ret_code_t err_code = gscm_local_db_cache_update(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - success = true; - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - /* Do nothing */ - break; - - case NRF_ERROR_BUSY: - set_procedure_as_pending = true; - break; - - case NRF_ERROR_STORAGE_FULL: - { - pm_evt_t event = - { - .evt_id = PM_EVT_STORAGE_FULL, - .conn_handle = conn_handle, - }; - - evt_send(&event); - break; - } - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - local_db_update(conn_handle, set_procedure_as_pending); - - return success; -} - - -/**@brief Function for sending a service changed indication in an event context, where no return - * code can be given. - * - * @details This function will do the procedure, and check the result, set a flag if needed, and - * send an event if needed. - * - * @param[in] conn_handle The connection to perform the procedure on. - */ -static void service_changed_send_in_evt(uint16_t conn_handle) -{ - bool sc_pending_state = true; - bool sc_sent_state = false; - ret_code_t err_code = gscm_service_changed_ind_send(conn_handle); - - switch (err_code) - { - case NRF_SUCCESS: - { - pm_evt_t event = - { - .evt_id = PM_EVT_SERVICE_CHANGED_IND_SENT, - .conn_handle = conn_handle, - }; - - sc_sent_state = true; - - evt_send(&event); - break; - } - - case NRF_ERROR_BUSY: - // Do nothing. - break; - - case NRF_ERROR_INVALID_STATE: - // CCCDs not enabled. Drop indication. - // Fallthrough. - - case NRF_ERROR_NOT_SUPPORTED: - // Service changed not supported. Drop indication. - sc_pending_state = false; - gscm_db_change_notification_done(im_peer_id_get_by_conn_handle(conn_handle)); - break; - - case BLE_ERROR_GATTS_SYS_ATTR_MISSING: - local_db_apply_in_evt(conn_handle); - break; - - case BLE_ERROR_INVALID_CONN_HANDLE: - // Do nothing. - break; - - default: - send_unexpected_error(conn_handle, err_code); - break; - } - - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, sc_pending_state); - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, sc_sent_state); -} - - -/**@brief Function for checking all flags for one id, and handling the ones that are set. - * - * @param[in] flag_id The flag id to check flags for. - */ -static void pending_flags_check(ble_conn_state_user_flag_id_t flag_id) -{ - // Quickly check if any flags are set. - if (sdk_mapped_flags_any_set(ble_conn_state_user_flag_collection(flag_id))) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - // Check each flag. - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - uint16_t conn_handle = conn_handle_list.flag_keys[i]; - if (ble_conn_state_user_flag_get(conn_handle, flag_id)) - { - // This flag is set. Handle depending on which flags we are checking. - if (flag_id == m_flag_local_db_apply_pending) - { - local_db_apply_in_evt(conn_handle); - } - else if (flag_id == m_flag_local_db_update_pending) - { - if (pm_mutex_lock(&m_db_update_in_progress_mutex, 0)) - { - if (local_db_update_in_evt(conn_handle)) - { - // Successfully started writing to flash. - return; - } - else - { - pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); - } - } - } - else if (flag_id == m_flag_service_changed_pending) - { - if (!ble_conn_state_user_flag_get(conn_handle, m_flag_service_changed_sent)) - { - service_changed_send_in_evt(conn_handle); - } - } - } - } - } -} - - -static __INLINE void apply_pending_flags_check(void) -{ - pending_flags_check(m_flag_local_db_apply_pending); -} - - -static __INLINE void update_pending_flags_check(void) -{ - pending_flags_check(m_flag_local_db_update_pending); -} - - -static __INLINE void service_changed_pending_flags_check(void) -{ - pending_flags_check(m_flag_service_changed_pending); -} - - -/**@brief Callback function for events from the ID Manager module. - * This function is registered in the ID Manager module. - * - * @param[in] p_event The event from the ID Manager module. - */ -void gcm_im_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_BONDED_PEER_CONNECTED: - local_db_apply_in_evt(p_event->conn_handle); - if (gscm_service_changed_ind_needed(p_event->conn_handle)) - { - ble_conn_state_user_flag_set(p_event->conn_handle, m_flag_service_changed_pending, true); - } - break; - default: - break; - } -} - - -/**@brief Callback function for events from the Peer Database module. - * This handler is extern in Peer Database. - * - * @param[in] p_event The event from the Security Dispatcher module. - */ -void gcm_pdb_evt_handler(pm_evt_t * p_event) -{ - if ( p_event->evt_id == PM_EVT_PEER_DATA_UPDATE_SUCCEEDED - && p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - switch (p_event->params.peer_data_update_succeeded.data_id) - { - case PM_PEER_DATA_ID_BONDING: - { - uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); - - if (conn_handle != BLE_CONN_HANDLE_INVALID) - { - local_db_update(conn_handle, true); - } - break; - } - - case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: - { - ret_code_t err_code; - pm_peer_data_flash_t peer_data; - - err_code = pdb_peer_data_ptr_get(p_event->peer_id, - PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - &peer_data); - - if (err_code == NRF_SUCCESS) - { - if (*peer_data.p_service_changed_pending) - { - uint16_t conn_handle = im_conn_handle_get(p_event->peer_id); - if (conn_handle != BLE_CONN_HANDLE_INVALID) - { - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, true); - service_changed_pending_flags_check(); - } - } - } - break; - } - - case PM_PEER_DATA_ID_GATT_LOCAL: - pm_mutex_unlock(&m_db_update_in_progress_mutex, 0); - // Expecting a call to update_pending_flags_check() immediately. - break; - - default: - /* No action */ - break; - } - } - - update_pending_flags_check(); -} - - -ret_code_t gcm_init() -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - m_flag_local_db_update_pending = ble_conn_state_user_flag_acquire(); - m_flag_local_db_apply_pending = ble_conn_state_user_flag_acquire(); - m_flag_service_changed_pending = ble_conn_state_user_flag_acquire(); - m_flag_service_changed_sent = ble_conn_state_user_flag_acquire(); - - if ((m_flag_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID) - || (m_flag_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID)) - { - return NRF_ERROR_INTERNAL; - } - - pm_mutex_init(&m_db_update_in_progress_mutex, 1); - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -/**@brief Callback function for BLE events from the SoftDevice. - * - * @param[in] p_ble_evt The BLE event from the SoftDevice. - */ -void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; - - switch (p_ble_evt->header.evt_id) - { - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - local_db_apply_in_evt(conn_handle); - break; - - case BLE_GATTS_EVT_SC_CONFIRM: - { - pm_evt_t event = - { - .evt_id = PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, - .peer_id = im_peer_id_get_by_conn_handle(conn_handle), - .conn_handle = conn_handle, - }; - - gscm_db_change_notification_done(event.peer_id); - - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_sent, false); - ble_conn_state_user_flag_set(conn_handle, m_flag_service_changed_pending, false); - evt_send(&event); - break; - } - - case BLE_GATTS_EVT_WRITE: - if (cccd_written(&p_ble_evt->evt.gatts_evt.params.write)) - { - local_db_update(conn_handle, true); - update_pending_flags_check(); - } - break; - } - - apply_pending_flags_check(); - service_changed_pending_flags_check(); -} - - -ret_code_t gcm_local_db_cache_update(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - local_db_update(conn_handle, true); - update_pending_flags_check(); - - return NRF_SUCCESS; -} - - -void gcm_local_database_has_changed(void) -{ - gscm_local_database_has_changed(); - - sdk_mapped_flags_key_list_t conn_handles = ble_conn_state_conn_handles(); - - for (uint16_t i = 0; i < conn_handles.len; i++) - { - if (im_peer_id_get_by_conn_handle(conn_handles.flag_keys[i]) == PM_PEER_ID_INVALID) - { - ble_conn_state_user_flag_set(conn_handles.flag_keys[i], m_flag_service_changed_pending, true); - } - } - - service_changed_pending_flags_check(); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h deleted file mode 100644 index 5ea1bcde1c..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatt_cache_manager.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef GATT_CACHE_MANAGER_H__ -#define GATT_CACHE_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** - * @cond NO_DOXYGEN - * @defgroup gatt_cache_manager GATT Cache Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT - * attributes. - */ - - -/**@brief Function for initializing the GATT Cache Manager module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t gcm_init(void); - - -/**@brief Function for dispatching SoftDevice events to the GATT Cache Manager module. - * - * @param[in] p_ble_evt The SoftDevice event. - */ -void gcm_ble_evt_handler(ble_evt_t const * p_ble_evt); - - -/**@brief Function for triggering local GATT database data to be stored persistently. - * - * @details Values are retrieved from SoftDevice and written to persistent storage. - * - * @note This operation happens asynchronously, so any errors are reported as events. - * - * @note This function is only needed when you want to override the regular functionality of the - * module, e.g. to immediately store to flash instead of waiting for the native logic to - * perform the update. - * - * @param[in] conn_handle Connection handle to perform update on. - * - * @retval NRF_SUCCESS Store operation started. - */ -ret_code_t gcm_local_db_cache_update(uint16_t conn_handle); - - -/**@brief Function for manually informing that the local database has changed. - * - * @details This causes a service changed notification to be sent to all bonded peers that - * subscribe to it. - */ -void gcm_local_database_has_changed(void); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* GATT_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c deleted file mode 100644 index b2d2aa6f52..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.c +++ /dev/null @@ -1,340 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "gatts_cache_manager.h" - -#include -#include "ble_gap.h" -#include "ble_err.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_database.h" -#include "id_manager.h" - - -// Syntactic sugar, two spoons. -#define SYS_ATTR_SYS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS) -#define SYS_ATTR_USR (BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS) -#define SYS_ATTR_BOTH (SYS_ATTR_SYS | SYS_ATTR_USR) - -static bool m_module_initialized; -static pm_peer_id_t m_current_sc_store_peer_id; - - -/**@brief Function for resetting the module variable(s) of the GSCM module. - */ -static void internal_state_reset() -{ - m_module_initialized = false; - m_current_sc_store_peer_id = PM_PEER_ID_INVALID; -} - - -//lint -save -e550 -/**@brief Function for storing service_changed_pending = true to flash for all peers, in sequence. - * - * This function aborts if it gets @ref NRF_ERROR_BUSY when trying to store. A subsequent call will - * continue where the last call was aborted. - */ -static void service_changed_pending_set(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret_code_t err_code; - // Use a uint32_t to enforce 4-byte alignment. - static const uint32_t service_changed_pending = true; - - //lint -save -e65 -e64 - pm_peer_data_const_t peer_data = - { - .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - .length_words = PM_SC_STATE_N_WORDS(), - .p_service_changed_pending = (bool*)&service_changed_pending, - }; - //lint -restore - - err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); - while ((m_current_sc_store_peer_id != PM_PEER_ID_INVALID) && (err_code != NRF_ERROR_BUSY)) - { - m_current_sc_store_peer_id = pdb_next_peer_id_get(m_current_sc_store_peer_id); - err_code = pdb_raw_store(m_current_sc_store_peer_id, &peer_data, NULL); - } -} -//lint -restore - - - -/**@brief Event handler for events from the Peer Database module. - * This function is extern in Peer Database. - * - * @param[in] p_event The event that has happend with peer id and flags. - */ -void gscm_pdb_evt_handler(pm_evt_t * p_event) -{ - if (m_current_sc_store_peer_id != PM_PEER_ID_INVALID) - { - service_changed_pending_set(); - } -} - - -ret_code_t gscm_init() -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t gscm_local_db_cache_update(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - ret_code_t err_code; - - if (peer_id == PM_PEER_ID_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - else - { - pm_peer_data_t peer_data; - uint16_t n_bufs = 1; - bool retry_with_bigger_buffer = false; - - do - { - retry_with_bigger_buffer = false; - - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, n_bufs++, &peer_data); - if (err_code == NRF_SUCCESS) - { - pm_peer_data_local_gatt_db_t * p_local_gatt_db = peer_data.p_local_gatt_db; - - p_local_gatt_db->flags = SYS_ATTR_BOTH; - - err_code = sd_ble_gatts_sys_attr_get(conn_handle, &p_local_gatt_db->data[0], &p_local_gatt_db->len, p_local_gatt_db->flags); - - if (err_code == NRF_SUCCESS) - { - err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, peer_id); - } - else - { - if (err_code == NRF_ERROR_DATA_SIZE) - { - // The sys attributes are bigger than the requested write buffer. - retry_with_bigger_buffer = true; - } - else if (err_code == NRF_ERROR_NOT_FOUND) - { - // There are no sys attributes in the GATT db, so nothing needs to be stored. - err_code = NRF_SUCCESS; - } - - ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL); - if (err_code_release != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - } - } - else if (err_code == NRF_ERROR_INVALID_PARAM) - { - // The sys attributes are bigger than the entire write buffer. - err_code = NRF_ERROR_DATA_SIZE; - } - } while (retry_with_bigger_buffer); - } - - return err_code; -} - - -ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - ret_code_t err_code; - pm_peer_data_flash_t peer_data; - uint8_t const * p_sys_attr_data = NULL; - uint16_t sys_attr_len = 0; - uint32_t sys_attr_flags = (SYS_ATTR_BOTH); - bool all_attributes_applied = true; - - if (peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data); - if (err_code == NRF_SUCCESS) - { - pm_peer_data_local_gatt_db_t const * p_local_gatt_db; - - p_local_gatt_db = peer_data.p_local_gatt_db; - p_sys_attr_data = p_local_gatt_db->data; - sys_attr_len = p_local_gatt_db->len; - sys_attr_flags = p_local_gatt_db->flags; - } - } - - do - { - err_code = sd_ble_gatts_sys_attr_set(conn_handle, p_sys_attr_data, sys_attr_len, sys_attr_flags); - - if (err_code == NRF_ERROR_NO_MEM) - { - err_code = NRF_ERROR_BUSY; - } - else if (err_code == NRF_ERROR_INVALID_STATE) - { - err_code = NRF_SUCCESS; - } - else if (err_code == NRF_ERROR_INVALID_DATA) - { - all_attributes_applied = false; - - if (sys_attr_flags & SYS_ATTR_USR) - { - // Try setting only system attributes. - sys_attr_flags = SYS_ATTR_SYS; - } - else if (p_sys_attr_data || sys_attr_len) - { - // Try reporting that none exist. - p_sys_attr_data = NULL; - sys_attr_len = 0; - sys_attr_flags = SYS_ATTR_BOTH; - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - } - } while (err_code == NRF_ERROR_INVALID_DATA); - - if (!all_attributes_applied) - { - err_code = NRF_ERROR_INVALID_DATA; - } - - return err_code; -} - -void gscm_local_database_has_changed(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - m_current_sc_store_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - service_changed_pending_set(); -} - - -bool gscm_service_changed_ind_needed(uint16_t conn_handle) -{ - ret_code_t err_code; - bool service_changed_state; - pm_peer_data_flash_t peer_data; - - peer_data.p_service_changed_pending = &service_changed_state; - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data); - - if (err_code != NRF_SUCCESS) - { - return false; - } - - return *peer_data.p_service_changed_pending; -} - - -ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle) -{ - static uint16_t start_handle; - const uint16_t end_handle = 0xFFFF; - ret_code_t err_code; - - err_code = sd_ble_gatts_initial_user_handle_get(&start_handle); - - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - do - { - err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle); - if (err_code == BLE_ERROR_INVALID_ATTR_HANDLE) - { - start_handle += 1; - } - } while (err_code == BLE_ERROR_INVALID_ATTR_HANDLE); - - return err_code; -} - - -void gscm_db_change_notification_done(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - // Use a uint32_t to enforce 4-byte alignment. - static const uint32_t service_changed_pending = false; - - //lint -save -e65 -e64 - pm_peer_data_const_t peer_data = - { - .data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, - .length_words = PM_SC_STATE_N_WORDS(), - .p_service_changed_pending = (bool*)&service_changed_pending, - }; - //lint -restore - - // Don't need to check return code, because all error conditions can be ignored. - //lint -save -e550 - (void) pdb_raw_store(peer_id, &peer_data, NULL); - //lint -restore -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h deleted file mode 100644 index a463344d28..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/gatts_cache_manager.h +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef GATTS_CACHE_MANAGER_H__ -#define GATTS_CACHE_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/** - * @cond NO_DOXYGEN - * @defgroup gatts_cache_manager GATT Server Cache Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT - * attributes pertaining to the GATT server role of the local device. - */ - - -/**@brief Function for initializing the GATT Server Cache Manager module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t gscm_init(void); - - -/**@brief Function for triggering local GATT database data to be stored persistently. Values are - * retrieved from the SoftDevice and written to persistent storage. - * - * @param[in] conn_handle Connection handle to perform update on. - * - * @retval NRF_SUCCESS Store operation started. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a - * bonded peer. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. - * @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with - * this GATT database. - * @retval NRF_ERROR_STORAGE_FULL No room in persistent_storage. Free up space; the - * operation will be automatically reattempted after the - * next FDS garbage collection procedure. - */ -ret_code_t gscm_local_db_cache_update(uint16_t conn_handle); - - -/**@brief Function for applying stored local GATT database data to the SoftDevice. Values are - * retrieved from persistent storage and given to the SoftDevice. - * - * @param[in] conn_handle Connection handle to apply values to. - * - * @retval NRF_SUCCESS Store operation started. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a - * bonded peer. - * @retval NRF_ERROR_INVALID_DATA The stored data was rejected by the SoftDevice, which - * probably means that the local database has changed. The - * system part of the sys_attributes was attempted applied, - * so service changed indications can be sent to subscribers. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later. - * @return An unexpected return value from an internal function call. - */ -ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle); - - -/**@brief Function for storing the fact that the local database has changed, for all currently - * bonded peers. - * - * @note This will cause a later call to @ref gscm_service_changed_ind_needed to return true for - * a connection with a currently bonded peer. - */ -void gscm_local_database_has_changed(void); - - -/**@brief Function for checking if a service changed indication should be sent. - * - * @param[in] conn_handle The connection to check. - * - * @return true if a service changed indication should be sent, false if not. - */ -bool gscm_service_changed_ind_needed(uint16_t conn_handle); - - -/**@brief Function for sending a service changed indication to a connected peer. - * - * @param[in] conn_handle The connection to send the indication on. - * - * @retval NRF_SUCCESS Indication sent or not needed. - * @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection. - * @retval NRF_ERROR_BUSY Unable to send indication at this time. Reattempt later. - * @retval BLE_ERROR_GATTS_SYS_ATTR_MISSING Information missing. Apply local cache, then reattempt. - * @retval NRF_ERROR_INVALID_PARAM From @ref sd_ble_gatts_service_changed. Unexpected. - * @retval NRF_ERROR_NOT_SUPPORTED Service changed characteristic is not present. - * @retval NRF_ERROR_INVALID_STATE Service changed cannot be indicated to this peer - * because the peer has not subscribed to it. - * @retval NRF_ERROR_INTERNAL An unexpected error happened. - */ -ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle); - - -/**@brief Function for specifying that a peer has been made aware of the latest local database - * change. - * - * @note After calling this, a later call to @ref gscm_service_changed_ind_needed will to return - * false for this peer unless @ref gscm_local_database_has_changed is called again. - * - * @param[in] peer_id The connection to send the indication on. - */ -void gscm_db_change_notification_done(pm_peer_id_t peer_id); - -/** @} - * @endcond -*/ - - -#ifdef __cplusplus -} -#endif - -#endif /* GATTS_CACHE_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c deleted file mode 100644 index dd1b5c0bd9..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.c +++ /dev/null @@ -1,1065 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "id_manager.h" - -#include -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_database.h" -#include "peer_data_storage.h" -#include "nrf_soc.h" - - -#define IM_MAX_CONN_HANDLES (20) -#define IM_NO_INVALID_CONN_HANDLES (0xFF) -#define IM_ADDR_CLEARTEXT_LENGTH (3) -#define IM_ADDR_CIPHERTEXT_LENGTH (3) - -// The number of registered event handlers. -#define IM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Identity Manager event handlers in Peer Manager and GATT Cache Manager. -extern void pm_im_evt_handler(pm_evt_t * p_event); -extern void gcm_im_evt_handler(pm_evt_t * p_event); - -// Identity Manager events' handlers. -// The number of elements in this array is IM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_im_evt_handler, - gcm_im_evt_handler -}; - - -typedef struct -{ - pm_peer_id_t peer_id; - uint16_t conn_handle; - ble_gap_addr_t peer_address; -} im_connection_t; - -static bool m_module_initialized; -static im_connection_t m_connections[IM_MAX_CONN_HANDLES]; -static ble_conn_state_user_flag_id_t m_conn_state_user_flag_id; - -static uint8_t m_wlisted_peer_cnt; -static pm_peer_id_t m_wlisted_peers[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - -#if (NRF_SD_BLE_API_VERSION <= 2) - static ble_gap_addr_t m_current_id_addr; -#endif - - -static void internal_state_reset() -{ - m_conn_state_user_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; - - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - m_connections[i].conn_handle = BLE_CONN_HANDLE_INVALID; - } -} - - -/**@brief Function for sending an event to all registered event handlers. - * - * @param[in] p_event The event to distribute. - */ -static void evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < IM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - -/**@brief Function finding a free position in m_connections. - * - * @detail All connection handles in the m_connections array are checked against the connection - * state module. The index of the first one that is not a connection handle for a current - * connection is returned. This position in the array can safely be used for a new connection. - * - * @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free - position exists. - */ -uint8_t get_free_connection() -{ - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - // Query the connection state module to check if the - // connection handle does not belong to a valid connection. - if (!ble_conn_state_user_flag_get(m_connections[i].conn_handle, m_conn_state_user_flag_id)) - { - return i; - } - } - // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. - return IM_NO_INVALID_CONN_HANDLES; -} - - -/**@brief Function finding a particular connection handle m_connections. - * - * @param[in] conn_handle The handle to find. - * - * @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the - * handle was not found. - */ -uint8_t get_connection_by_conn_handle(uint16_t conn_handle) -{ - if (ble_conn_state_user_flag_get(conn_handle, m_conn_state_user_flag_id)) - { - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - if (m_connections[i].conn_handle == conn_handle) - { - return i; - } - } - } - // If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES. - return IM_NO_INVALID_CONN_HANDLES; -} - - -/**@brief Function for registering a new connection instance. - * - * @param[in] conn_handle The handle of the new connection. - * @param[in] p_ble_addr The address used to connect. - * - * @return Either the index of the new connection in the array or IM_NO_INVALID_CONN_HANDLES if no - * free position exists. - */ -uint8_t new_connection(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) -{ - uint8_t conn_index = IM_NO_INVALID_CONN_HANDLES; - - if ((p_ble_addr != NULL) && (conn_handle != BLE_CONN_HANDLE_INVALID)) - { - ble_conn_state_user_flag_set(conn_handle, m_conn_state_user_flag_id, true); - - conn_index = get_connection_by_conn_handle(conn_handle); - if (conn_index == IM_NO_INVALID_CONN_HANDLES) - { - conn_index = get_free_connection(); - } - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - m_connections[conn_index].conn_handle = conn_handle; - m_connections[conn_index].peer_id = PM_PEER_ID_INVALID; - m_connections[conn_index].peer_address = *p_ble_addr; - } - } - return conn_index; -} - - -/**@brief Function checking the validity of an IRK - * - * @detail An all-zero IRK is not valid. This function will check if a given IRK is valid. - * - * @param[in] p_irk The IRK for which the validity is going to be checked. - * - * @retval true The IRK is valid. - * @retval false The IRK is invalid. - */ -bool is_valid_irk(ble_gap_irk_t const * p_irk) -{ - NRF_PM_DEBUG_CHECK(p_irk != NULL); - - for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++) - { - if (p_irk->irk[i] != 0) - { - return true; - } - } - return false; -} - - -/**@brief Function for comparing two addresses to determine if they are identical - * - * @note The address type need to be identical, as well as every bit in the address itself. - * - * @param[in] p_addr1 The first address to be compared. - * @param[in] p_addr2 The second address to be compared. - * - * @retval true The addresses are identical. - * @retval false The addresses are not identical. - */ -bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2) -{ - // @note emdi: use NRF_PM_DEBUG_CHECK ? - if ((p_addr1 == NULL) || (p_addr2 == NULL)) - { - return false; - } - - // Check that the addr type is identical, return false if it is not - if (p_addr1->addr_type != p_addr2->addr_type) - { - return false; - } - - // Check if the addr bytes are is identical - return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0); -} - - -void im_ble_evt_handler(ble_evt_t const * ble_evt) -{ - ble_gap_evt_t gap_evt; - pm_peer_id_t bonded_matching_peer_id; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (ble_evt->header.evt_id != BLE_GAP_EVT_CONNECTED) - { - // Nothing to do. - return; - } - - gap_evt = ble_evt->evt.gap_evt; - bonded_matching_peer_id = PM_PEER_ID_INVALID; - - if ( gap_evt.params.connected.peer_addr.addr_type - != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - /* Search the database for bonding data matching the one that triggered the event. - * Public and static addresses can be matched on address alone, while resolvable - * random addresses can be resolved agains known IRKs. Non-resolvable random addresses - * are never matching because they are not longterm form of identification. - */ - - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - pds_peer_data_iterate_prepare(); - - switch (gap_evt.params.connected.peer_addr.addr_type) - { - case BLE_GAP_ADDR_TYPE_PUBLIC: - case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: - { - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (addr_compare(&gap_evt.params.connected.peer_addr, - &peer_data.p_bonding_data->peer_ble_id.id_addr_info)) - { - bonded_matching_peer_id = peer_id; - break; - } - } - } - break; - - case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE: - { - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_address_resolve(&gap_evt.params.connected.peer_addr, - &peer_data.p_bonding_data->peer_ble_id.id_info)) - { - bonded_matching_peer_id = peer_id; - break; - } - } - } - break; - - default: - NRF_PM_DEBUG_CHECK(false); - break; - } - } - - uint8_t new_index = new_connection(gap_evt.conn_handle, - &gap_evt.params.connected.peer_addr); - UNUSED_VARIABLE(new_index); - - if (bonded_matching_peer_id != PM_PEER_ID_INVALID) - { - im_new_peer_id(gap_evt.conn_handle, bonded_matching_peer_id); - - // Send a bonded peer event - pm_evt_t im_evt; - im_evt.conn_handle = gap_evt.conn_handle; - im_evt.peer_id = bonded_matching_peer_id; - im_evt.evt_id = PM_EVT_BONDED_PEER_CONNECTED; - evt_send(&im_evt); - } -} - - -/**@brief Function to compare two sets of bonding data to check if they belong to the same device. - * @note Invalid irks will never match even though they are identical. - * - * @param[in] p_bonding_data1 First bonding data for comparison - * @param[in] p_bonding_data2 Second bonding data for comparison - * - * @return True if the input matches, false if it does not. - */ -bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, - pm_peer_data_bonding_t const * p_bonding_data2) -{ - NRF_PM_DEBUG_CHECK(p_bonding_data1 != NULL); - NRF_PM_DEBUG_CHECK(p_bonding_data2 != NULL); - - ble_gap_addr_t const * p_addr1 = &p_bonding_data1->peer_ble_id.id_addr_info; - ble_gap_addr_t const * p_addr2 = &p_bonding_data2->peer_ble_id.id_addr_info; - - bool duplicate_irk = ((memcmp(p_bonding_data1->peer_ble_id.id_info.irk, - p_bonding_data2->peer_ble_id.id_info.irk, - BLE_GAP_SEC_KEY_LEN) == 0) - && is_valid_irk(&p_bonding_data1->peer_ble_id.id_info) - && is_valid_irk(&p_bonding_data2->peer_ble_id.id_info)); - - bool duplicate_addr = addr_compare(p_addr1, p_addr2); - - bool id_addrs = ((p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - && (p_addr1->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - && (p_addr2->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)); - - return (duplicate_addr && id_addrs) || (duplicate_irk && !id_addrs); -} - - -pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, - pm_peer_id_t peer_id_skip) -{ - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data_duplicate; - - NRF_PM_DEBUG_CHECK(p_bonding_data != NULL); - - pds_peer_data_iterate_prepare(); - - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data_duplicate)) - { - if ( (peer_id != peer_id_skip) - && im_is_duplicate_bonding_data(p_bonding_data, - peer_data_duplicate.p_bonding_data)) - { - return peer_id; - } - } - return PM_PEER_ID_INVALID; -} - - -ret_code_t im_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - m_conn_state_user_flag_id = ble_conn_state_user_flag_acquire(); - if (m_conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - #if (NRF_SD_BLE_API_VERSION <= 2) - ret_code_t ret_code = sd_ble_gap_address_get(&m_current_id_addr); - if (ret_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - #endif - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle) -{ - uint8_t conn_index; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - conn_index = get_connection_by_conn_handle(conn_handle); - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - return m_connections[conn_index].peer_id; - } - - return PM_PEER_ID_INVALID; -} - - -ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr) -{ - uint8_t conn_index; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_ble_addr != NULL); - - conn_index = get_connection_by_conn_handle(conn_handle); - - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - *p_ble_addr = m_connections[conn_index].peer_address; - return NRF_SUCCESS; - } - - return NRF_ERROR_NOT_FOUND; -} - - -bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, - ble_gap_master_id_t const * p_master_id2) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_master_id1 != NULL); - NRF_PM_DEBUG_CHECK(p_master_id2 != NULL); - - if (!im_master_id_is_valid(p_master_id1)) - { - return false; - } - - if (p_master_id1->ediv != p_master_id2->ediv) - { - return false; - } - - return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0); -} - - -pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id) -{ - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_master_id != NULL); - - pds_peer_data_iterate_prepare(); - - // For each stored peer, check if the master_id matches p_master_id - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->own_ltk.master_id) || - im_master_ids_compare(p_master_id, &peer_data.p_bonding_data->peer_ltk.master_id)) - { - // If a matching master ID is found then return the peer ID. - return peer_id; - } - } - - // If no matching master ID is found return PM_PEER_ID_INVALID. - return PM_PEER_ID_INVALID; -} - - -uint16_t im_conn_handle_get(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++) - { - if (peer_id == m_connections[i].peer_id) - { - return m_connections[i].conn_handle; - } - } - return BLE_CONN_HANDLE_INVALID; -} - - -bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (p_master_id->ediv != 0) - { - return true; - } - - for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++) - { - if (p_master_id->rand[i] != 0) - { - return true; - } - } - return false; -} - - -/**@brief Function to set the peer ID associated with a connection handle. - * - * @param[in] conn_handle The connection handle. - * @param[in] peer_id The peer ID to associate with @c conn_handle. - */ -static void peer_id_set(uint16_t conn_handle, pm_peer_id_t peer_id) -{ - uint8_t conn_index = get_connection_by_conn_handle(conn_handle); - if (conn_index != IM_NO_INVALID_CONN_HANDLES) - { - m_connections[conn_index].peer_id = peer_id; - } -} - - -void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - peer_id_set(conn_handle, peer_id); -} - - -ret_code_t im_peer_free(pm_peer_id_t peer_id) -{ - uint16_t conn_handle; - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - conn_handle = im_conn_handle_get(peer_id); - ret = pdb_peer_free(peer_id); - - if ((conn_handle != BLE_CONN_HANDLE_INVALID) && (ret == NRF_SUCCESS)) - { - peer_id_set(conn_handle, PM_PEER_ID_INVALID); - } - return ret; -} - - -/**@brief Given a list of peers, loads their GAP address and IRK into the provided buffers. - */ -static ret_code_t peers_id_keys_get(pm_peer_id_t const * p_peers, - uint32_t peer_cnt, - ble_gap_addr_t * p_gap_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_gap_irks, - uint32_t * p_irk_cnt) -{ - ret_code_t ret; - - pm_peer_data_bonding_t bond_data; - pm_peer_data_t peer_data; - - uint32_t const buf_size = sizeof(bond_data); - - bool copy_addrs = false; - bool copy_irks = false; - - NRF_PM_DEBUG_CHECK(p_peers != NULL); - - // One of these two has to be provided. - NRF_PM_DEBUG_CHECK((p_gap_addrs != NULL) || (p_gap_irks != NULL)); - - if ((p_gap_addrs != NULL) && (p_addr_cnt != NULL)) - { - NRF_PM_DEBUG_CHECK((*p_addr_cnt) >= peer_cnt); - - copy_addrs = true; - *p_addr_cnt = 0; - } - - if ((p_gap_irks != NULL) && (p_irk_cnt != NULL)) - { - NRF_PM_DEBUG_CHECK((*p_irk_cnt) >= peer_cnt); - - copy_irks = true; - *p_irk_cnt = 0; - } - - memset(&peer_data, 0x00, sizeof(peer_data)); - peer_data.p_bonding_data = &bond_data; - - // Read through flash memory and look for peers ID keys. - - for (uint32_t i = 0; i < peer_cnt; i++) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, - &peer_data, &buf_size); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data coulnd't be found in flash or peer ID is not valid. - return NRF_ERROR_NOT_FOUND; - } - - uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; - - if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && - (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) - { - // The address shared by the peer during bonding can't be used for whitelisting. - return BLE_ERROR_GAP_INVALID_BLE_ADDR; - } - - // Copy the GAP address. - if (copy_addrs) - { - memcpy(&p_gap_addrs[i], &bond_data.peer_ble_id.id_addr_info, sizeof(ble_gap_addr_t)); - (*p_addr_cnt)++; - } - - // Copy the IRK. - if (copy_irks) - { - memcpy(&p_gap_irks[i], bond_data.peer_ble_id.id_info.irk, BLE_GAP_SEC_KEY_LEN); - (*p_irk_cnt)++; - } - } - - return NRF_SUCCESS; -} - - -ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - #if (NRF_SD_BLE_API_VERSION >= 3) - - ret_code_t ret; - pm_peer_data_t peer_data; - pm_peer_data_bonding_t bond_data; - - ble_gap_id_key_t keys[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; - ble_gap_id_key_t const * key_ptrs[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; - - if ((p_peers == NULL) || (peer_cnt == 0)) - { - // Clear the device identities list. - return sd_ble_gap_device_identities_set(NULL, NULL, 0); - } - - peer_data.p_bonding_data = &bond_data; - uint32_t const buf_size = sizeof(bond_data); - - memset(keys, 0x00, sizeof(keys)); - for (uint32_t i = 0; i < BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; i++) - { - key_ptrs[i] = &keys[i]; - } - - for (uint32_t i = 0; i < peer_cnt; i++) - { - memset(&bond_data, 0x00, sizeof(bond_data)); - - // Read peer data from flash. - ret = pds_peer_data_read(p_peers[i], PM_PEER_DATA_ID_BONDING, - &peer_data, &buf_size); - - if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM)) - { - // Peer data coulnd't be found in flash or peer ID is not valid. - return NRF_ERROR_NOT_FOUND; - } - - uint8_t const addr_type = bond_data.peer_ble_id.id_addr_info.addr_type; - - if ((addr_type != BLE_GAP_ADDR_TYPE_PUBLIC) && - (addr_type != BLE_GAP_ADDR_TYPE_RANDOM_STATIC)) - { - // The address shared by the peer during bonding can't be whitelisted. - return BLE_ERROR_GAP_INVALID_BLE_ADDR; - } - - // Copy data to the buffer. - memcpy(&keys[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t)); - } - - return sd_ble_gap_device_identities_set(key_ptrs, NULL, peer_cnt); - - #else - - return NRF_ERROR_NOT_SUPPORTED; - - #endif -} - - -#if (NRF_SD_BLE_API_VERSION <= 2) - -static ret_code_t address_set_v2(uint8_t cycle_mode, ble_gap_addr_t * p_addr) -{ - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - ret_code_t ret = sd_ble_gap_address_set(cycle_mode, p_addr); - - switch (ret) - { - case NRF_SUCCESS: - case NRF_ERROR_BUSY: - case NRF_ERROR_INVALID_STATE: - case NRF_ERROR_INVALID_PARAM: // If cycle_mode is not AUTO or NONE. - case BLE_ERROR_GAP_INVALID_BLE_ADDR: // If the GAP address is not valid. - return ret; - - default: - return NRF_ERROR_INTERNAL; - } -} - -#endif - - -ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ret_code_t ret; - ble_gap_addr_t current_addr; - - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - (void) sd_ble_gap_address_get(¤t_addr); - - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, (ble_gap_addr_t *)p_addr); - if (ret != NRF_SUCCESS) - { - return ret; - } - - if ( current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE - || current_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - // If currently using privacy, it must be re-enabled. - // We force AUTO when privacy is enabled. - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, ¤t_addr); - if (ret != NRF_SUCCESS) - { - return ret; - } - } - - memcpy(&m_current_id_addr, p_addr, sizeof(ble_gap_addr_t)); - - return NRF_SUCCESS; - - #else - - return sd_ble_gap_addr_set(p_addr); - - #endif -} - - -ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr) -{ - NRF_PM_DEBUG_CHECK(p_addr != NULL); - - #if (NRF_SD_BLE_API_VERSION <= 2) - memcpy(p_addr, &m_current_id_addr, sizeof(ble_gap_addr_t)); - return NRF_SUCCESS; - #else - return sd_ble_gap_addr_get(p_addr); - #endif -} - - -ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ret_code_t ret; - ble_gap_addr_t privacy_addr; - ble_gap_irk_t current_irk; - ble_opt_t privacy_options; - ble_opt_t current_privacy_options; - - NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); - - privacy_addr.addr_type = p_privacy_params->private_addr_type; - privacy_options.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; - privacy_options.gap_opt.privacy.interval_s = p_privacy_params->private_addr_cycle_s; - current_privacy_options.gap_opt.privacy.p_irk = ¤t_irk; - - // Can not fail. - (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); - (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, &privacy_options); - - if (p_privacy_params->privacy_mode == BLE_GAP_PRIVACY_MODE_OFF) - { - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_NONE, &m_current_id_addr); - } - else - { - ret = address_set_v2(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &privacy_addr); - } - - if (ret != NRF_SUCCESS) - { - // Restore previous settings. - (void) sd_ble_opt_set(BLE_GAP_OPT_PRIVACY, ¤t_privacy_options); - } - - // NRF_ERROR_BUSY, - // NRF_ERROR_INVALID_STATE, - // NRF_ERROR_INVALID_PARAM, if address type is not valid. - return ret; - - #else - - return sd_ble_gap_privacy_set(p_privacy_params); - - #endif -} - - -ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params) -{ - #if (NRF_SD_BLE_API_VERSION <= 2) - - ble_gap_addr_t cur_addr; - ble_opt_t cur_privacy_opt; - - NRF_PM_DEBUG_CHECK(p_privacy_params != NULL); - NRF_PM_DEBUG_CHECK(p_privacy_params->p_device_irk != NULL); - - cur_privacy_opt.gap_opt.privacy.p_irk = p_privacy_params->p_device_irk; - - // Can not fail. - (void) sd_ble_gap_address_get(&cur_addr); - - if ( cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE - || cur_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) - { - p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; - p_privacy_params->private_addr_type = cur_addr.addr_type; - } - else - { - p_privacy_params->privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - } - - // Can not fail. - (void) sd_ble_opt_get(BLE_GAP_OPT_PRIVACY, &cur_privacy_opt); - - p_privacy_params->private_addr_cycle_s = cur_privacy_opt.gap_opt.privacy.interval_s; - - return NRF_SUCCESS; - - #else - - return sd_ble_gap_privacy_get(p_privacy_params); - - #endif -} - - -/* Create a whitelist for the user using the cached list of peers. - * This whitelist is meant to be provided by the application to the Advertising module. - */ -ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt) -{ - // One of the two buffers has to be provided. - NRF_PM_DEBUG_CHECK((p_addrs != NULL) || (p_irks != NULL)); - NRF_PM_DEBUG_CHECK((p_addr_cnt != NULL) || (p_irk_cnt != NULL)); - - if (((p_addr_cnt != NULL) && (m_wlisted_peer_cnt > *p_addr_cnt)) || - ((p_irk_cnt != NULL) && (m_wlisted_peer_cnt > *p_irk_cnt))) - { - // The size of the cached list of peers is larger than the provided buffers. - return NRF_ERROR_NO_MEM; - } - - // NRF_SUCCESS or - // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. - // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. - return peers_id_keys_get(m_wlisted_peers, m_wlisted_peer_cnt, - p_addrs, p_addr_cnt, - p_irks, p_irk_cnt); -} - - -/* Copies the peers to whitelist into a local cache. - * The cached list will be used by im_whitelist_get() to retrieve the active whitelist. - * For SoftDevices 3x, also loads the peers' GAP addresses and whitelists them using - * sd_ble_gap_whitelist_set(). - */ -ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - // Clear the cache of whitelisted peers. - memset(m_wlisted_peers, 0x00, sizeof(m_wlisted_peers)); - - if ((p_peers == NULL) || (peer_cnt == 0)) - { - // Clear the current whitelist. - m_wlisted_peer_cnt = 0; - #if (NRF_SD_BLE_API_VERSION >= 3) - // NRF_SUCCESS, or - // BLE_GAP_ERROR_WHITELIST_IN_USE - return sd_ble_gap_whitelist_set(NULL, 0); - #else - // The cached list of whitelisted peers is already cleared; nothing to do. - return NRF_SUCCESS; - #endif - } - - // @todo emdi: should not ever cache more than BLE_GAP_WHITELIST_ADDR_MAX_COUNT... - - // Copy the new whitelisted peers. - m_wlisted_peer_cnt = peer_cnt; - memcpy(m_wlisted_peers, p_peers, sizeof(pm_peer_id_t) * peer_cnt); - - #if (NRF_SD_BLE_API_VERSION >= 3) - - ret_code_t ret; - uint32_t wlist_addr_cnt = 0; - - ble_gap_addr_t const * addr_ptrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - ble_gap_addr_t addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; - - memset(addrs, 0x00, sizeof(addrs)); - - // Fetch GAP addresses for these peers, but don't fetch IRKs. - ret = peers_id_keys_get(p_peers, peer_cnt, addrs, &wlist_addr_cnt, NULL, NULL); - - if (ret != NRF_SUCCESS) - { - // NRF_ERROR_NOT_FOUND, if a peer or its data were not found. - // BLE_ERROR_GAP_INVALID_BLE_ADDR, if a peer address can not be used for whitelisting. - return ret; - } - - for (uint32_t i = 0; i < BLE_GAP_WHITELIST_ADDR_MAX_COUNT; i++) - { - addr_ptrs[i] = &addrs[i]; - } - - // NRF_ERROR_DATA_SIZE, if peer_cnt > BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - // BLE_ERROR_GAP_WHITELIST_IN_USE, if a whitelist is in use. - return sd_ble_gap_whitelist_set(addr_ptrs, peer_cnt); - - #else - - return NRF_SUCCESS; - - #endif -} - - -/**@brief Function for calculating the ah() hash function described in Bluetooth core specification - * 4.2 section 3.H.2.2.2. - * - * @detail BLE uses a hash function to calculate the first half of a resolvable address - * from the second half of the address and an irk. This function will use the ECB - * periferal to hash these data acording to the Bluetooth core specification. - * - * @note The ECB expect little endian input and output. - * This function expect big endian and will reverse the data as necessary. - * - * @param[in] p_k The key used in the hash function. - * For address resolution this is should be the irk. - * The array must have a length of 16. - * @param[in] p_r The rand used in the hash function. For generating a new address - * this would be a random number. For resolving a resolvable address - * this would be the last half of the address being resolved. - * The array must have a length of 3. - * @param[out] p_local_hash The result of the hash operation. For address resolution this - * will match the first half of the address being resolved if and only - * if the irk used in the hash function is the same one used to generate - * the address. - * The array must have a length of 16. - */ -void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash) -{ - nrf_ecb_hal_data_t ecb_hal_data; - - for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++) - { - ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i]; - } - - memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH); - - for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++) - { - ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i]; - } - - // Can only return NRF_SUCCESS. - (void) sd_ecb_block_encrypt(&ecb_hal_data); - - for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++) - { - p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i]; - } -} - - -bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH]; - uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH]; - uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH]; - - if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - { - return false; - } - - memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH); - memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH); - ah(p_irk->irk, prand, local_hash); - - return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h deleted file mode 100644 index 1350a4a853..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/id_manager.h +++ /dev/null @@ -1,327 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_ID_MANAGER_H__ -#define PEER_ID_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup id_manager ID Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for keeping track of peer identities - * (IRK and peer address). - */ - - -/**@brief Function for initializing the Identity manager. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an error occurred. - */ -ret_code_t im_init(void); - - -/**@brief Function for dispatching SoftDevice events to the ID Manager module. - * - * @param[in] p_ble_evt The SoftDevice event. - */ -void im_ble_evt_handler(ble_evt_t const * p_ble_evt); - - -/**@brief Function for getting the corresponding peer ID from a connection handle. - * - * @param[in] conn_handle The connection handle. - * - * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. - */ -pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle); - - -/**@brief Function for getting the corresponding peer ID from a master ID (EDIV and rand). - * - * @param[in] p_master_id The master ID. - * - * @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved. - */ -pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t const * p_master_id); - - -/**@brief Function for getting the corresponding connection handle from a peer ID. - * - * @param[in] peer_id The peer ID. - * - * @return The corresponding connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be - * resolved. - */ -uint16_t im_conn_handle_get(pm_peer_id_t peer_id); - - -/**@brief Function for comparing two master ids - * @note Two invalid master IDs will not match. - * - * @param[in] p_master_id1 First master id for comparison - * @param[in] p_master_id2 Second master id for comparison - * - * @return True if the input matches, false if it does not. - */ -bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1, - ble_gap_master_id_t const * p_master_id2); - - -/**@brief Function for getting the BLE address used by the peer when connecting. - * - * @param[in] conn_handle The connection handle. - * @param[out] p_ble_addr The BLE address used by the peer when the connection specified by - * conn_handle was established. - * - * @retval NRF_SUCCESS The address was found and copied. - * @retval BLE_ERROR_CONN_HANDLE_INVALID conn_handle does not refer to an active connection. - * @retval NRF_ERROR_NULL p_ble_addr was NULL. - */ -ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr); - - -/**@brief Function for checking if a master ID is valid or invalid - * - * @param[in] p_master_id The master ID. - * - * @retval true The master id is valid. - * @retval false The master id is invalid (i.e. all zeros). - */ -bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id); - - -/**@brief Function for checking if two pieces of bonding data correspond to the same peer. - * - * @param[in] p_bonding_data1 The first piece of bonding data to check. - * @param[in] p_bonding_data2 The second piece of bonding data to check. - * - * @retval true The bonding data correspond to the same peer. - * @retval false The bonding data do not correspond to the same peer. - */ -bool im_is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1, - pm_peer_data_bonding_t const * p_bonding_data2); - - -/**@brief Function for finding if we are already bonded to a peer. - * - * @param[in] p_bonding_data The bonding data to check. - * @param[in] peer_id_skip Optional peer to ignore when searching for duplicates. - * - * @return An existing peer ID for the peer, or PM_PEER_ID_INVALID if none was found. - */ -pm_peer_id_t im_find_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data, - pm_peer_id_t peer_id_skip); - - -/**@brief Function for reporting that a new peer ID has been allocated for a specified connection. - * - * @param[in] conn_handle The connection. - * @param[in] peer_id The new peer ID. - */ -void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id); - - -/**@brief Function for deleting all of a peer's data from flash and disassociating it from any - * connection handles it is associated with. - * - * @param[in] peer_id The peer to free. - * - * @return Any error code returned by @ref pdb_peer_free. - */ -ret_code_t im_peer_free(pm_peer_id_t peer_id); - - -/**@brief Function to set the local Bluetooth identity address. - * - * @details The local Bluetooth identity address is the address that identifies this device to other - * peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are - * running. - * - * @note This address will be distributed to the peer during bonding. - * If the address changes, the address stored in the peer device will not be valid and the - * ability to reconnect using the old address will be lost. - * - * @note By default the SoftDevice will set an address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC - * upon being enabled. The address is a random number populated during the IC manufacturing - * process and remains unchanged for the lifetime of each IC. - * - * @param[in] p_addr Pointer to address structure. - * - * @retval NRF_SUCCESS Address successfully set. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the GAP address is invalid. - * @retval NRF_ERROR_BUSY Could not process at this time. Process SoftDevice events - * and retry. - * @retval NRF_ERROR_INVALID_STATE The identity address cannot be changed while advertising, - * scanning, or while in a connection. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t im_id_addr_set(ble_gap_addr_t const * p_addr); - - -/**@brief Function to get the local Bluetooth identity address. - * - * @note This will always return the identity address irrespective of the privacy settings, - * i.e. the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. - * - * @param[out] p_addr Pointer to address structure to be filled in. - * - * @retval NRF_SUCCESS If the address was successfully retrieved. - */ -ret_code_t im_id_addr_get(ble_gap_addr_t * p_addr); - - -/**@brief Function to set privacy settings. - * - * @details Privacy settings cannot be set while advertising, scanning, or while in a connection. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If privacy options were set successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. - * @retval NRF_ERROR_INVALID_PARAM If the address type is not valid. - * @retval NRF_ERROR_BUSY If the request could not be processed at this time. - * Process SoftDevice events and retry. - * @retval NRF_ERROR_INVALID_STATE Privacy settings cannot be changed while BLE roles using - * privacy are enabled. - */ -ret_code_t im_privacy_set(pm_privacy_params_t const * p_privacy_params); - - -/**@brief Function to retrieve the current privacy settings. - * - * @details The privacy settings returned include the current device irk as well. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS Successfully retrieved privacy settings. - * @retval NRF_ERROR_NULL @c p_privacy_params is NULL. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t im_privacy_get(pm_privacy_params_t * p_privacy_params); - - -/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). - * - * @details This function will use the ECB peripheral to resolve a resolvable address. - * This can be used to resolve the identity of a device distributing a random - * resolvable address based on any IRKs you have received earlier. If an address is - * resolved by an IRK, the device distributing the address must also know the IRK. - * - * @param[in] p_addr A random resolvable address. - * @param[in] p_irk An identity resolution key (IRK). - * - * @retval true The irk used matched the one used to create the address. - * @retval false The irk used did not match the one used to create the address, or an argument was - * NULL. - */ -bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - - -/**@brief Function for setting / clearing the whitelist. - * - * @param p_peers The peers to whitelist. Pass NULL to clear the whitelist. - * @param peer_cnt The number of peers to whitelist. Pass zero to clear the whitelist. - * - * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. - * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is in use. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used - * for whitelisting. - * @retval NRF_ERROR_NOT_FOUND If any peer or its data could not be found. - * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - */ -ret_code_t im_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t const peer_cnt); - - -/**@brief Retrieves the current whitelist, set by a previous call to @ref im_whitelist_set. - * - * @param[out] A buffer where to copy the GAP addresses. - * @param[inout] In: the size of the @p p_addrs buffer. - * Out: the number of address copied into the buffer. - * @param[out] A buffer where to copy the IRKs. - * @param[inout] In: the size of the @p p_irks buffer. - * Out: the number of IRKs copied into the buffer. - * - * @retval NRF_SUCCESS If the whitelist was successfully retreived. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If any peer has an address which can not be used for - * whitelisting. - * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers - * can not be found anymore. It might have been deleted in - * the meanwhile. - * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. - */ -ret_code_t im_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt); - - -/**@brief Set the device identities list. - */ -ret_code_t im_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_ID_MANAGER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c deleted file mode 100644 index aa25bf29fa..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.c +++ /dev/null @@ -1,685 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_data_storage.h" - -#include -#include -#include "sdk_errors.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_id.h" -#include "fds.h" - - -// Macro for verifying that the peer id is within a valid range. -#define VERIFY_PEER_ID_IN_RANGE(id) VERIFY_FALSE((id >= PM_PEER_ID_N_AVAILABLE_IDS), \ - NRF_ERROR_INVALID_PARAM) - -// Macro for verifying that the peer data id is withing a valid range. -#define VERIFY_PEER_DATA_ID_IN_RANGE(id) VERIFY_TRUE(peer_data_id_is_valid(id), \ - NRF_ERROR_INVALID_PARAM) - -// The number of registered event handlers. -#define PDS_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Peer Data Storage event handler in Peer Database. -extern void pdb_pds_evt_handler(pm_evt_t *); - -// Peer Data Storage events' handlers. -// The number of elements in this array is PDS_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pdb_pds_evt_handler, -}; - -static bool m_module_initialized = false; -static bool m_peer_delete_queued = false; -static bool m_peer_delete_ongoing = false; - -// A token used for Flash Data Storage searches. -static fds_find_token_t m_fds_ftok; - - -// Function for dispatching events to all registered event handlers. -static void pds_evt_send(pm_evt_t * p_event) -{ - p_event->conn_handle = BLE_CONN_HANDLE_INVALID; - - for (uint32_t i = 0; i < PDS_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -// Function to convert peer IDs to file IDs. -static uint16_t peer_id_to_file_id(pm_peer_id_t peer_id) -{ - return (uint16_t)(peer_id + PEER_ID_TO_FILE_ID); -} - - -// Function to convert peer data id to type id. -static pm_peer_id_t file_id_to_peer_id(uint16_t file_id) -{ - return (pm_peer_id_t)(file_id + FILE_ID_TO_PEER_ID); -} - - -// Function to convert peer data IDs to record keys. -static uint16_t peer_data_id_to_record_key(pm_peer_data_id_t peer_data_id) -{ - return (uint16_t)(peer_data_id + DATA_ID_TO_RECORD_KEY); -} - - -// Function to convert record keys to peer data IDs. -static pm_peer_data_id_t record_key_to_peer_data_id(uint16_t record_key) -{ - return (pm_peer_data_id_t)(record_key + RECORD_KEY_TO_DATA_ID); -} - - -// Function for checking whether a file ID is relevant for the Peer Manager. -static bool file_id_within_pm_range(uint16_t file_id) -{ - return ((PDS_FIRST_RESERVED_FILE_ID <= file_id) - && (file_id <= PDS_LAST_RESERVED_FILE_ID)); -} - - -// Function for checking whether a record key is relevant for the Peer Manager. -static bool record_key_within_pm_range(uint16_t record_key) -{ - return ((PDS_FIRST_RESERVED_RECORD_KEY <= record_key) - && (record_key <= PDS_LAST_RESERVED_RECORD_KEY)); -} - - -static bool peer_data_id_is_valid(pm_peer_data_id_t data_id) -{ - return ((data_id == PM_PEER_DATA_ID_BONDING) || - (data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING) || - (data_id == PM_PEER_DATA_ID_GATT_LOCAL) || - (data_id == PM_PEER_DATA_ID_GATT_REMOTE) || - (data_id == PM_PEER_DATA_ID_PEER_RANK) || - (data_id == PM_PEER_DATA_ID_APPLICATION)); -} - - -/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] peer_id The peer the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(pm_peer_id_t peer_id, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .peer_id = peer_id, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - pds_evt_send(&error_evt); -} - - -// Function for deleting all data beloning to a peer. -// These operations will be sent to FDS one at a time. -static void peer_data_delete() -{ - ret_code_t ret; - pm_peer_id_t peer_id; - uint16_t file_id; - fds_record_desc_t desc; - fds_find_token_t ftok; - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - peer_id = peer_id_get_next_deleted(PM_PEER_ID_INVALID); - - while ( (peer_id != PM_PEER_ID_INVALID) - && (fds_record_find_in_file(peer_id_to_file_id(peer_id), &desc, &ftok) - == FDS_ERR_NOT_FOUND)) - { - peer_id_free(peer_id); - peer_id = peer_id_get_next_deleted(peer_id); - } - - if (!m_peer_delete_ongoing && (peer_id != PM_PEER_ID_INVALID)) - { - m_peer_delete_ongoing = true; - - file_id = peer_id_to_file_id(peer_id); - ret = fds_file_delete(file_id); - - if (ret == FDS_ERR_NO_SPACE_IN_QUEUES) - { - m_peer_delete_queued = true; - } - else if (ret != NRF_SUCCESS) - { - m_peer_delete_ongoing = false; - - send_unexpected_error(peer_id, ret); - } - } -} - - -static ret_code_t peer_data_find(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - fds_record_desc_t * const p_desc) -{ - ret_code_t ret; - fds_find_token_t ftok; - - NRF_PM_DEBUG_CHECK(peer_id < PM_PEER_ID_N_AVAILABLE_IDS); - NRF_PM_DEBUG_CHECK(peer_data_id_is_valid(data_id)); - NRF_PM_DEBUG_CHECK(p_desc != NULL); - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - - uint16_t file_id = peer_id_to_file_id(peer_id); - uint16_t record_key = peer_data_id_to_record_key(data_id); - - ret = fds_record_find(file_id, record_key, p_desc, &ftok); - - if (ret != FDS_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - return NRF_SUCCESS; -} - - -static void peer_ids_load() -{ - fds_record_desc_t record_desc; - fds_flash_record_t record; - fds_find_token_t ftok; - - memset(&ftok, 0x00, sizeof(fds_find_token_t)); - - uint16_t const record_key = peer_data_id_to_record_key(PM_PEER_DATA_ID_BONDING); - - while (fds_record_find_by_key(record_key, &record_desc, &ftok) == FDS_SUCCESS) - { - pm_peer_id_t peer_id; - - // It is safe to ignore the return value since the descriptor was - // just obtained and also 'record' is different from NULL. - (void)fds_record_open(&record_desc, &record); - peer_id = file_id_to_peer_id(record.p_header->file_id); - (void)fds_record_close(&record_desc); - - (void)peer_id_allocate(peer_id); - } -} - - -static void fds_evt_handler(fds_evt_t const * const p_fds_evt) -{ - pm_evt_t pds_evt = - { - .peer_id = file_id_to_peer_id(p_fds_evt->write.file_id) - }; - - switch (p_fds_evt->id) - { - case FDS_EVT_WRITE: - case FDS_EVT_UPDATE: - case FDS_EVT_DEL_RECORD: - if ( file_id_within_pm_range(p_fds_evt->write.file_id) - || record_key_within_pm_range(p_fds_evt->write.record_key)) - { - pds_evt.params.peer_data_update_succeeded.data_id - = record_key_to_peer_data_id(p_fds_evt->write.record_key); - pds_evt.params.peer_data_update_succeeded.action - = (p_fds_evt->id == FDS_EVT_DEL_RECORD) ? PM_PEER_DATA_OP_DELETE - : PM_PEER_DATA_OP_UPDATE; - pds_evt.params.peer_data_update_succeeded.token = p_fds_evt->write.record_id; - - if (p_fds_evt->result == FDS_SUCCESS) - { - pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; - pds_evt.params.peer_data_update_succeeded.flash_changed = true; - } - else - { - pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED; - pds_evt.params.peer_data_update_failed.error = p_fds_evt->result; - } - - pds_evt_send(&pds_evt); - } - break; - - case FDS_EVT_DEL_FILE: - if ( file_id_within_pm_range(p_fds_evt->del.file_id) - && (p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY)) - { - if (p_fds_evt->result == FDS_SUCCESS) - { - pds_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED; - peer_id_free(pds_evt.peer_id); - } - else - { - pds_evt.evt_id = PM_EVT_PEER_DELETE_FAILED; - } - - m_peer_delete_queued = false; - m_peer_delete_ongoing = false; - - peer_data_delete(); - - pds_evt_send(&pds_evt); - } - break; - - case FDS_EVT_GC: - pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTED; - pds_evt.peer_id = PM_PEER_ID_INVALID; - - pds_evt_send(&pds_evt); - break; - - default: - // No action. - break; - } - - if (m_peer_delete_queued) - { - m_peer_delete_queued = false; - peer_data_delete(); - } -} - - -ret_code_t pds_init() -{ - ret_code_t ret; - - // Check for re-initialization if debugging. - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - ret = fds_register(fds_evt_handler); - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - ret = fds_init(); - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_STORAGE_FULL; - } - - peer_id_init(); - peer_ids_load(); - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_data, - uint32_t const * const p_buf_len) -{ - ret_code_t ret; - fds_record_desc_t rec_desc; - fds_flash_record_t rec_flash; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_data != NULL); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - ret = peer_data_find(peer_id, data_id, &rec_desc); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - // Shouldn't fail, unless the record was deleted in the meanwhile or the CRC check has failed. - ret = fds_record_open(&rec_desc, &rec_flash); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - p_data->data_id = data_id; - p_data->length_words = rec_flash.p_header->length_words; - - // If p_buf_len is NULL, provide a pointer to data in flash, otherwise, - // check that the buffer is large enough and copy the data in flash into the buffer. - if (p_buf_len == NULL) - { - // The cast is necessary because if no buffer is provided, we just copy the pointer, - // but in that case it should be considered a pointer to const data by the caller, - // since it is a pointer to data in flash. - p_data->p_all_data = (void*)rec_flash.p_data; - } - else - { - uint32_t const data_len_bytes = (p_data->length_words * sizeof(uint32_t)); - - if ((*p_buf_len) >= data_len_bytes) - { - memcpy(p_data->p_all_data, rec_flash.p_data, data_len_bytes); - } - else - { - return NRF_ERROR_NO_MEM; - } - } - - // Shouldn't fail unless the record was already closed, in which case it can be ignored. - (void)fds_record_close(&rec_desc); - - return NRF_SUCCESS; -} - - -void pds_peer_data_iterate_prepare(void) -{ - memset(&m_fds_ftok, 0x00, sizeof(fds_find_token_t)); -} - - -bool pds_peer_data_iterate(pm_peer_data_id_t data_id, - pm_peer_id_t * const p_peer_id, - pm_peer_data_flash_t * const p_data) -{ - ret_code_t ret; - uint16_t rec_key; - fds_record_desc_t rec_desc; - fds_flash_record_t rec_flash; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_id != NULL); - NRF_PM_DEBUG_CHECK(p_data != NULL); - - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - rec_key = peer_data_id_to_record_key(data_id); - - if (fds_record_find_by_key(rec_key, &rec_desc, &m_fds_ftok) != NRF_SUCCESS) - { - return false; - } - - ret = fds_record_open(&rec_desc, &rec_flash); - - if (ret != NRF_SUCCESS) - { - // It can only happen if the record was deleted after the call to fds_record_find_by_key(), - // before we could open it, or if CRC support was enabled in Flash Data Storage at compile - // time and the CRC check failed. - return false; - } - - p_data->data_id = data_id; - p_data->length_words = rec_flash.p_header->length_words; - p_data->p_all_data = rec_flash.p_data; - - *p_peer_id = file_id_to_peer_id(rec_flash.p_header->file_id); - - (void)fds_record_close(&rec_desc); - - return true; -} - - -ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t * p_prepare_token) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - NRF_PM_DEBUG_CHECK(p_prepare_token != NULL); - - VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); - - ret = fds_reserve((fds_reserve_token_t*)p_prepare_token, p_peer_data->length_words); - - switch (ret) - { - case FDS_SUCCESS: - return NRF_SUCCESS; - - case FDS_ERR_RECORD_TOO_LARGE: - return NRF_ERROR_INVALID_LENGTH; - - case FDS_ERR_NO_SPACE_IN_FLASH: - return NRF_ERROR_STORAGE_FULL; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(prepare_token != PDS_PREPARE_TOKEN_INVALID); - - ret = fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); - - if (ret != FDS_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - return NRF_SUCCESS; -} - - -ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t prepare_token, - pm_store_token_t * p_store_token) -{ - ret_code_t ret; - fds_record_t rec; - fds_record_desc_t rec_desc; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id); - - // Prepare the record to be stored in flash. - rec.file_id = peer_id_to_file_id(peer_id); - rec.key = peer_data_id_to_record_key(p_peer_data->data_id); - rec.data.p_data = (void*)p_peer_data->p_all_data; - rec.data.length_words = p_peer_data->length_words; - - ret = peer_data_find(peer_id, p_peer_data->data_id, &rec_desc); - - if (ret == NRF_ERROR_NOT_FOUND) - { - // No previous data exists in flash. - if (prepare_token == PDS_PREPARE_TOKEN_INVALID) - { - // No space was previously reserved. - ret = fds_record_write(&rec_desc, &rec); - } - else - { - // Space for this record was previously reserved. - ret = fds_record_write_reserved(&rec_desc, &rec, (fds_reserve_token_t*)&prepare_token); - } - } - else // NRF_SUCCESS - { - if (prepare_token != PDS_PREPARE_TOKEN_INVALID) - { - (void)fds_reserve_cancel((fds_reserve_token_t*)&prepare_token); - } - - // Update existing record. - ret = fds_record_update(&rec_desc, &rec); - } - - switch (ret) - { - case FDS_SUCCESS: - if (p_store_token != NULL) - { - // Update the store token. - (void)fds_record_id_from_desc(&rec_desc, (uint32_t*)p_store_token); - } - return NRF_SUCCESS; - - case FDS_ERR_BUSY: - case FDS_ERR_NO_SPACE_IN_QUEUES: - return NRF_ERROR_BUSY; - - case FDS_ERR_NO_SPACE_IN_FLASH: - return NRF_ERROR_STORAGE_FULL; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - ret_code_t ret; - fds_record_desc_t record_desc; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_PEER_ID_IN_RANGE(peer_id); - VERIFY_PEER_DATA_ID_IN_RANGE(data_id); - - ret = peer_data_find(peer_id, data_id, &record_desc); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_NOT_FOUND; - } - - ret = fds_record_delete(&record_desc); - - switch (ret) - { - case FDS_SUCCESS: - return NRF_SUCCESS; - - case FDS_ERR_NO_SPACE_IN_QUEUES: - return NRF_ERROR_BUSY; - - default: - return NRF_ERROR_INTERNAL; - } -} - - -pm_peer_id_t pds_peer_id_allocate(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_allocate(PM_PEER_ID_INVALID); -} - - -ret_code_t pds_peer_id_free(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - VERIFY_PEER_ID_IN_RANGE(peer_id); - - (void)peer_id_delete(peer_id); - peer_data_delete(); - - return NRF_SUCCESS; -} - - -bool pds_peer_id_is_allocated(pm_peer_id_t peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_is_allocated(peer_id); -} - - -pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_get_next_used(prev_peer_id); -} - - -pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_get_next_deleted(prev_peer_id); -} - - -uint32_t pds_peer_count_get(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return peer_id_n_ids(); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h deleted file mode 100644 index 2138a3b61d..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_data_storage.h +++ /dev/null @@ -1,270 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_DATA_STORAGE_H__ -#define PEER_DATA_STORAGE_H__ - - -#include -#include "sdk_errors.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_manager_internal.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup peer_data_storage Peer Data Storage - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides a Peer Manager-specific API - * to the persistent storage. - * - * @details This module uses Flash Data Storage (FDS) to interface with persistent storage. - */ - -#define PDS_PREPARE_TOKEN_INVALID (0) /**< Invalid value for prepare token. */ -#define PDS_FIRST_RESERVED_FILE_ID (0xC000) /**< The beginning of the range of file IDs reserved for Peer Manager. */ -#define PDS_LAST_RESERVED_FILE_ID (0xFFFE) /**< The end of the range of file IDs reserved for Peer Manager. */ -#define PDS_FIRST_RESERVED_RECORD_KEY (0xC000) /**< The beginning of the range of record keys reserved for Peer Manager. */ -#define PDS_LAST_RESERVED_RECORD_KEY (0xFFFE) /**< The end of the range of record keys reserved for Peer Manager. */ - -#define PEER_ID_TO_FILE_ID ( PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting a @ref pm_peer_id_t to an FDS file ID. -#define FILE_ID_TO_PEER_ID (-PDS_FIRST_RESERVED_FILE_ID) //!< Macro for converting an FDS file ID to a @ref pm_peer_id_t. -#define DATA_ID_TO_RECORD_KEY ( PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting a @ref pm_peer_data_id_t to an FDS record ID. -#define RECORD_KEY_TO_DATA_ID (-PDS_FIRST_RESERVED_RECORD_KEY) //!< Macro for converting an FDS record ID to a @ref pm_peer_data_id_t. - - -/**@brief Function for initializing the module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_STORAGE_FULL If no flash pages were available for use. - * @retval NRF_ERROR_INTERNAL If the module couldn't register with the flash filesystem. - */ -ret_code_t pds_init(void); - - -/**@brief Function for reading peer data in flash. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to retrieve. - * @param[out] p_data The peer data. May not be @c NULL. - * @param[in] p_buf_len Length of the provided buffer, in bytes. Pass @c NULL to only copy - * a pointer to the data in flash. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. - * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. - */ -ret_code_t pds_peer_data_read(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_data, - uint32_t const * const p_buf_len); - - -/**@brief Function to prepare iterating over peer data in flash using @ref pds_peer_data_iterate. - * Call this function once each time before iterating using @ref pds_peer_data_iterate. - */ -void pds_peer_data_iterate_prepare(void); - - -/**@brief Function for iterating peers' data in flash. - * Always call @ref pds_peer_data_iterate_prepare before starting iterating. - * - * @param[in] data_id The peer data to iterate over. - * @param[out] p_peer_id The peer the data belongs to. - * @param[out] p_data The peer data in flash. - * - * @retval true If the operation was successful. - * @retval false If the data was not found in flash, or another error occurred. - */ -bool pds_peer_data_iterate(pm_peer_data_id_t data_id, - pm_peer_id_t * const p_peer_id, - pm_peer_data_flash_t * const p_data); - - -/**@brief Function for reserving space in flash to store data. - * - * @param[in] p_peer_data The data to be stored in flash. Only data length and type (ID) are - * relevant for this operation. May not be @c NULL. - * @param[out] p_prepare_token A token identifying the reserved space. May not be @c NULL. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If the data ID in @p p_peer_data is invalid. - * @retval NRF_ERROR_INVALID_LENGTH If data length exceeds the maximum allowed length. - * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_space_reserve(pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t * p_prepare_token); - - -/**@brief Function for undoing a previous call to @ref pds_space_reserve. - * - * @param[in] prepare_token A token identifying the reservation to cancel. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_space_reserve_cancel(pm_prepare_token_t prepare_token); - - -/**@brief Function for storing peer data in flash. If the same piece of data already exists for the - * given peer, it will be updated. This operation is asynchronous. - * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED - * event. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] p_peer_data The peer data. May not be @c NULL. - * @param[in] prepare_token A token identifying the reservation made in flash to store the data. - * Pass @ref PDS_PREPARE_TOKEN_INVALID if no space was reserved. - * @param[out] p_store_token A token identifying this particular store operation. The token can be - * used to identify events pertaining to this operation. Pass @p NULL - * if not used. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or the data ID in @p_peer_data are invalid. - * @retval NRF_ERROR_STORAGE_FULL If no space is available in flash. This can only happen if - * @p p_prepare_token is @ref PDS_PREPARE_TOKEN_INVALID. - * @retval NRF_ERROR_BUSY If the flash filesystem was busy. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_const_t const * p_peer_data, - pm_prepare_token_t prepare_token, - pm_store_token_t * p_store_token); - - -/**@brief Function for deleting peer data in flash. This operation is asynchronous. - * Expect a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or @ref PM_EVT_PEER_DATA_UPDATE_FAILED - * event. - * - * @param[in] peer_id The peer the data belongs to - * @param[in] data_id The data to delete. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. - * @retval NRF_ERROR_BUSY If the flash filesystem was busy. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t pds_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for claiming an unused peer ID. - * - * @retval PM_PEER_ID_INVALID If no peer ID was available. - */ -pm_peer_id_t pds_peer_id_allocate(void); - - -/**@brief Function for freeing a peer ID and deleting all data associated with it in flash. - * - * @param[in] peer_id The ID of the peer to free. - * - * @retval NRF_SUCCESS The operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id is invalid. - */ -ret_code_t pds_peer_id_free(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is in use. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true @p peer_id is in use. - * @retval false @p peer_id is free. - */ -bool pds_peer_id_is_allocated(pm_peer_id_t peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The first ordinary peer ID If @p prev_peer_id is @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID If @p prev_peer_id is the last ordinary peer ID or the module - * is not initialized. - */ -pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. - * Can be used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID pending deletion. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module - * is not initialized. - */ -pm_peer_id_t pds_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pds_peer_count_get(void); - - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_DATA_STORAGE_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c deleted file mode 100644 index 9216136959..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.c +++ /dev/null @@ -1,831 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_database.h" - -#include -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "peer_data_storage.h" -#include "pm_buffer.h" - - -/**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer. - * - * @param[in] data_id The data ID to verify. - */ -// @note emdi: could this maybe be a function? -#define VERIFY_DATA_ID_WRITE_BUF(data_id) \ -do \ -{ \ - if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \ - { \ - return NRF_ERROR_INVALID_PARAM; \ - } \ -} while (0) - - -// The number of registered event handlers. -#define PDB_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Peer Database event handlers in other Peer Manager submodules. -extern void pm_pdb_evt_handler(pm_evt_t * p_event); -extern void sm_pdb_evt_handler(pm_evt_t * p_event); -extern void gscm_pdb_evt_handler(pm_evt_t * p_event); -extern void gcm_pdb_evt_handler(pm_evt_t * p_event); - -// Peer Database events' handlers. -// The number of elements in this array is PDB_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_pdb_evt_handler, - sm_pdb_evt_handler, - gscm_pdb_evt_handler, - gcm_pdb_evt_handler, -}; - - -/**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written - * or cancelled. - */ -typedef struct -{ - pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */ - pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */ - pm_prepare_token_t prepare_token; /**< Token given by Peer Data Storage if room in flash has been reserved. */ - pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. This is used as the check for whether such an operation has been successfully requested. */ - uint8_t n_bufs; /**< The number of buffer blocks containing peer data. */ - uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */ - uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */ - uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */ -} pdb_buffer_record_t; - - -static bool m_module_initialized; -static pm_buffer_t m_write_buffer; /**< The state of the write buffer. */ -static pdb_buffer_record_t m_write_buffer_records[PM_FLASH_BUFFERS]; /**< The available write buffer records. */ -static uint32_t m_n_pending_writes; /**< The number of pending (Not yet successfully requested in Peer Data Storage) store operations. */ - - - -/**@brief Function for invalidating a record of a write buffer allocation. - * - * @param[in] p_record The record to invalidate. - */ -static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record) -{ - p_record->peer_id = PM_PEER_ID_INVALID; - p_record->data_id = PM_PEER_DATA_ID_INVALID; - p_record->buffer_block_id = PM_BUFFER_INVALID_ID; - p_record->store_busy = false; - p_record->store_flash_full = false; - p_record->n_bufs = 0; - p_record->prepare_token = PDS_PREPARE_TOKEN_INVALID; - p_record->store_token = PM_STORE_TOKEN_INVALID; -} - - -/**@brief Function for finding a record of a write buffer allocation. - * - * @param[in] peer_id The peer ID in the record. - * @param[inout] p_index In: The starting index, out: The index of the record - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, uint32_t * p_index) -{ - for (uint32_t i = *p_index; i < PM_FLASH_BUFFERS; i++) - { - if ((m_write_buffer_records[i].peer_id == peer_id)) - { - *p_index = i; - return &m_write_buffer_records[i]; - } - } - return NULL; -} - - -/**@brief Function for finding a record of a write buffer allocation. - * - * @param[in] peer_id The peer ID in the record. - * @param[in] data_id The data ID in the record. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id) -{ - uint32_t index = 0; - pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); - - while ((p_record != NULL) && ( (p_record->data_id != data_id) - || (p_record->store_busy) - || (p_record->store_flash_full) - || (p_record->store_token != PM_STORE_TOKEN_INVALID))) - { - index++; - p_record = write_buffer_record_find_next(peer_id, &index); - } - - return p_record; -} - - -/**@brief Function for finding a record of a write buffer allocation that has been sent to be stored. - * - * @param[in] store_token The store token received when store was called for the record. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_stored(pm_store_token_t store_token) -{ - for (int i = 0; i < PM_FLASH_BUFFERS; i++) - { - if (m_write_buffer_records[i].store_token == store_token) - { - return &m_write_buffer_records[i]; - } - } - return NULL; -} - - -/**@brief Function for finding an available record for write buffer allocation. - * - * @return A pointer to the available record, or NULL if none was found. - */ -static pdb_buffer_record_t * write_buffer_record_find_unused(void) -{ - return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID); -} - - -/**@brief Function for gracefully deactivating a write buffer record. - * - * @details This function will first release any buffers, then invalidate the record. - * - * @param[inout] p_write_buffer_record The record to release. - * - * @return A pointer to the matching record, or NULL if none was found. - */ -static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record) -{ - for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - - write_buffer_record_invalidate(p_write_buffer_record); -} - - -/**@brief Function for claiming and activating a write buffer record. - * - * @param[out] pp_write_buffer_record The claimed record. - * @param[in] peer_id The peer ID this record should have. - * @param[in] data_id The data ID this record should have. - */ -static void write_buffer_record_acquire(pdb_buffer_record_t ** pp_write_buffer_record, - pm_peer_id_t peer_id, - pm_peer_data_id_t data_id) -{ - if (pp_write_buffer_record == NULL) - { - return; - } - *pp_write_buffer_record = write_buffer_record_find_unused(); - if (*pp_write_buffer_record == NULL) - { - // This also means the buffer is full. - return; - } - (*pp_write_buffer_record)->peer_id = peer_id; - (*pp_write_buffer_record)->data_id = data_id; -} - - -/**@brief Function for dispatching outbound events to all registered event handlers. - * - * @param[in] p_event The event to dispatch. - */ -static void pdb_evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < PDB_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for resetting the internal state of the Peer Database module. - * - * @param[out] p_event The event to dispatch. - */ -static void internal_state_reset() -{ - for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) - { - write_buffer_record_invalidate(&m_write_buffer_records[i]); - } -} - - -static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs) -{ - uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE; - p_peer_data->data_id = data_id; - - p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory; - p_peer_data->length_words = BYTES_TO_WORDS(n_bytes); -} - - -static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs) -{ - peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs); -} - - -static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data) -{ - switch (p_peer_data->data_id) - { - case PM_PEER_DATA_ID_BONDING: - p_peer_data->length_words = PM_BONDING_DATA_N_WORDS(); - break; - case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING: - p_peer_data->length_words = PM_SC_STATE_N_WORDS(); - break; - case PM_PEER_DATA_ID_PEER_RANK: - p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS(); - break; - case PM_PEER_DATA_ID_GATT_LOCAL: - p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len); - break; - default: - // No action needed. - break; - } -} - - -/**@brief Function for writing data into persistent storage. Writing happens asynchronously. - * - * @note This will unlock the data after it has been written. - * - * @param[in] p_write_buffer_record The write buffer record to write into persistent storage. - * - * @retval NRF_SUCCESS Data storing was successfully started. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some - * space, the operation will be reattempted after the next compress - * procedure. This error will not happen if - * @ref pdb_write_buf_store_prepare is called beforehand. - * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. - * @retval NRF_ERROR_INVALID_STATE Module is not initialized. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t write_buf_store(pdb_buffer_record_t * p_write_buffer_record) -{ - ret_code_t err_code = NRF_SUCCESS; - pm_peer_data_const_t peer_data = {.data_id = p_write_buffer_record->data_id}; - uint8_t * p_buffer_memory; - - p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_const_point_to_buffer(&peer_data, - p_write_buffer_record->data_id, - p_buffer_memory, - p_write_buffer_record->n_bufs); - write_buf_length_words_set(&peer_data); - - err_code = pds_peer_data_store(p_write_buffer_record->peer_id, - &peer_data, - p_write_buffer_record->prepare_token, - &p_write_buffer_record->store_token); - - if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full) - { - m_n_pending_writes--; - } - - switch (err_code) - { - case NRF_SUCCESS: - p_write_buffer_record->store_busy = false; - p_write_buffer_record->store_flash_full = false; - break; - - case NRF_ERROR_BUSY: - m_n_pending_writes++; - - p_write_buffer_record->store_busy = true; - p_write_buffer_record->store_flash_full = false; - - err_code = NRF_SUCCESS; - break; - - case NRF_ERROR_STORAGE_FULL: - m_n_pending_writes++; - - p_write_buffer_record->store_busy = false; - p_write_buffer_record->store_flash_full = true; - break; - - case NRF_ERROR_INVALID_PARAM: - // No action. - break; - - default: - err_code = NRF_ERROR_INTERNAL; - break; - } - - return err_code; -} - - -/**@brief This calls @ref write_buf_store and sends events based on the return value. - * - * See @ref write_buf_store for more info. - * - * @return Whether or not the store operation succeeded. - */ -static bool write_buf_store_in_event(pdb_buffer_record_t * p_write_buffer_record) -{ - ret_code_t err_code; - pm_evt_t event; - - err_code = write_buf_store(p_write_buffer_record); - if (err_code != NRF_SUCCESS) - { - event.conn_handle = BLE_CONN_HANDLE_INVALID; - event.peer_id = p_write_buffer_record->peer_id; - - if (err_code == NRF_ERROR_STORAGE_FULL) - { - event.evt_id = PM_EVT_STORAGE_FULL; - } - else - { - event.evt_id = PM_EVT_ERROR_UNEXPECTED; - event.params.error_unexpected.error = err_code; - } - - pdb_evt_send(&event); - - return false; - } - - return true; -} - - -/**@brief This reattempts store operations on write buffers, that previously failed because of @ref - * NRF_ERROR_BUSY or @ref NRF_ERROR_STORAGE_FULL errors. - * - * param[in] retry_flash_full Whether to retry operations that failed because of an - * @ref NRF_ERROR_STORAGE_FULL error. - */ -static void reattempt_previous_operations(bool retry_flash_full) -{ - // Reattempt previously rejected store operations. - - if (m_n_pending_writes == 0) - { - return; - } - - for (uint32_t i = 0; i < PM_FLASH_BUFFERS; i++) - { - if ((m_write_buffer_records[i].store_busy) - || (m_write_buffer_records[i].store_flash_full && retry_flash_full)) - { - bool success = write_buf_store_in_event(&m_write_buffer_records[i]); - - if (!success) - { - break; - } - } - } -} - - -/**@brief Function for handling events from the Peer Data Storage module. - * This function is extern in Peer Data Storage. - * - * @param[in] p_event The event to handle. - */ -void pdb_pds_evt_handler(pm_evt_t * p_event) -{ - pdb_buffer_record_t * p_write_buffer_record; - bool evt_send = true; - bool retry_flash_full = false; - - p_write_buffer_record = write_buffer_record_find_stored(p_event->params.peer_data_update_succeeded.token); - - switch (p_event->evt_id) - { - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - && (p_write_buffer_record != NULL)) - { - // The write came from PDB. - write_buffer_record_release(p_write_buffer_record); - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - if ( (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - && (p_write_buffer_record != NULL)) - { - // The write came from PDB, retry. - m_n_pending_writes++; - p_write_buffer_record->store_token = PM_STORE_TOKEN_INVALID; - p_write_buffer_record->store_busy = true; - evt_send = false; - } - break; - - case PM_EVT_FLASH_GARBAGE_COLLECTED: - retry_flash_full = true; - break; - - default: - break; - } - - if (evt_send) - { - // Forward the event to all registered Peer Database event handlers. - pdb_evt_send(p_event); - } - - reattempt_previous_operations(retry_flash_full); -} - - -ret_code_t pdb_init() -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - internal_state_reset(); - - PM_BUFFER_INIT(&m_write_buffer, PM_FLASH_BUFFERS, PDB_WRITE_BUF_SIZE, ret); - - if (ret != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -pm_peer_id_t pdb_peer_allocate(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_id_allocate(); -} - - -ret_code_t pdb_peer_free(pm_peer_id_t peer_id) -{ - ret_code_t err_code_in = NRF_SUCCESS; - ret_code_t err_code_out = NRF_SUCCESS; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint32_t index = 0; - pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index); - - while (p_record != NULL) - { - err_code_in = pdb_write_buf_release(peer_id, p_record->data_id); - - if ( (err_code_in != NRF_SUCCESS) - && (err_code_in != NRF_ERROR_NOT_FOUND)) - { - err_code_out = NRF_ERROR_INTERNAL; - } - - index++; - p_record = write_buffer_record_find_next(peer_id, &index); - } - - if (err_code_out == NRF_SUCCESS) - { - err_code_in = pds_peer_id_free(peer_id); - - if (err_code_in == NRF_SUCCESS) - { - // No action needed. - } - else if (err_code_in == NRF_ERROR_INVALID_PARAM) - { - err_code_out = NRF_ERROR_INVALID_PARAM; - } - else - { - err_code_out = NRF_ERROR_INTERNAL; - } - } - - return err_code_out; -} - - -ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_flash_t * const p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - // Pass NULL to only retrieve a pointer. - return pds_peer_data_read(peer_id, data_id, (pm_peer_data_t*)p_peer_data, NULL); -} - - - -ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - uint32_t n_bufs, - pm_peer_data_t * p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_PARAM_NOT_NULL(p_peer_data); - VERIFY_DATA_ID_WRITE_BUF(data_id); - - if ( (n_bufs == 0) - || (n_bufs > PM_FLASH_BUFFERS) - || !pds_peer_id_is_allocated(peer_id)) - { - return NRF_ERROR_INVALID_PARAM; - } - - pdb_buffer_record_t * p_write_buffer_record; - uint8_t * p_buffer_memory; - bool new_record = false; - bool find_new_buffer = false; - - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - find_new_buffer = true; - } - else if (p_write_buffer_record->n_bufs < n_bufs) - { - // @TODO: Copy? - // Existing buffer is too small. - for (uint8_t i = 0; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - write_buffer_record_invalidate(p_write_buffer_record); - find_new_buffer = true; - } - else if (p_write_buffer_record->n_bufs > n_bufs) - { - // Release excess blocks. - for (uint8_t i = n_bufs; i < p_write_buffer_record->n_bufs; i++) - { - pm_buffer_release(&m_write_buffer, p_write_buffer_record->buffer_block_id + i); - } - } - else - { - // Do nothing. - } - - if (find_new_buffer) - { - // No buffer exists. - write_buffer_record_acquire(&p_write_buffer_record, peer_id, data_id); - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_BUSY; - } - } - - if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) - { - p_write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_write_buffer, n_bufs); - - if (p_write_buffer_record->buffer_block_id == PM_BUFFER_INVALID_ID) - { - write_buffer_record_invalidate(p_write_buffer_record); - return NRF_ERROR_BUSY; - } - - new_record = true; - } - - p_write_buffer_record->n_bufs = n_bufs; - - p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, p_write_buffer_record->buffer_block_id); - - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs); - if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL)) - { - p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words); - } - - return NRF_SUCCESS; -} - - -ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret_code_t err_code = NRF_SUCCESS; - pdb_buffer_record_t * p_write_buffer_record; - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID) - { - err_code = pds_space_reserve_cancel(p_write_buffer_record->prepare_token); - if (err_code != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - } - - write_buffer_record_release(p_write_buffer_record); - - return err_code; -} - - -ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_DATA_ID_WRITE_BUF(data_id); - - ret_code_t err_code = NRF_SUCCESS; - pdb_buffer_record_t * p_write_buffer_record; - p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID) - { - uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_write_buffer, - p_write_buffer_record->buffer_block_id); - pm_peer_data_const_t peer_data = {.data_id = data_id}; - - if (p_buffer_memory == NULL) - { - return NRF_ERROR_INTERNAL; - } - - peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs); - - write_buf_length_words_set(&peer_data); - - err_code = pds_space_reserve(&peer_data, &p_write_buffer_record->prepare_token); - if (err_code == NRF_ERROR_INVALID_LENGTH) - { - return NRF_ERROR_INTERNAL; - } - } - - return err_code; -} - - -ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_id_t new_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - VERIFY_DATA_ID_WRITE_BUF(data_id); - - pdb_buffer_record_t * p_write_buffer_record = write_buffer_record_find(peer_id, data_id); - - if (p_write_buffer_record == NULL) - { - return NRF_ERROR_NOT_FOUND; - } - - p_write_buffer_record->peer_id = new_peer_id; - p_write_buffer_record->data_id = data_id; - return write_buf_store(p_write_buffer_record); -} - - -ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_data_delete(peer_id, data_id); -} - - -uint32_t pdb_n_peers(void) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_count_get(); -} - - -pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_next_peer_id_get(prev_peer_id); -} - - -pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_next_deleted_peer_id_get(prev_peer_id); -} - - -ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_peer_data) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_peer_data != NULL); - - // Provide the buffer length in bytes. - uint32_t const data_len_bytes = (p_peer_data->length_words * sizeof(uint32_t)); - return pds_peer_data_read(peer_id, data_id, p_peer_data, &data_len_bytes); -} - - -ret_code_t pdb_raw_store(pm_peer_id_t peer_id, - pm_peer_data_const_t * p_peer_data, - pm_store_token_t * p_store_token) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - return pds_peer_data_store(peer_id, p_peer_data, PDS_PREPARE_TOKEN_INVALID, p_store_token); -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h deleted file mode 100644 index 5e1e0fb6b8..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_database.h +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_DATABASE_H__ -#define PEER_DATABASE_H__ - -#include -#include "peer_manager_types.h" -#include "peer_manager_internal.h" -#include "sdk_errors.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @cond NO_DOXYGEN - * @defgroup peer_database Peer Database - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for simple management of reading and - * writing of peer data into persistent storage. - * - */ - -#define PDB_WRITE_BUF_SIZE (sizeof(pm_peer_data_bonding_t)) //!< The size (in bytes) of each block in the internal buffer accessible via @ref pdb_write_buf_get. - - -/**@brief Function for initializing the module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL An unexpected error happened. - */ -ret_code_t pdb_init(void); - - -/**@brief Function for allocating persistent bond storage for a peer. - * - * @return The ID of the newly allocated storage. - * @retval PM_PEER_ID_INVALID If no peer ID is available. - */ -pm_peer_id_t pdb_peer_allocate(void); - - -/**@brief Function for freeing a peer's persistent bond storage. - * - * @note This function will call @ref pdb_write_buf_release on the data for this peer. - * - * @param[in] peer_id ID to be freed. - * - * @retval NRF_SUCCESS Peer ID was released and clear operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM Peer ID was invalid. - */ -ret_code_t pdb_peer_free(pm_peer_id_t peer_id); - - -/**@brief Function for retrieving a pointer to peer data in flash (read-only). - * - * @note Dereferencing this pointer is not the safest thing to do if interrupts are enabled, - * because Flash Data Storage garbage collection might move the data around. Either disable - * interrupts while using the data, or use @ref pdb_peer_data_load. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to read. - * @param[out] p_peer_data The peer data, read-only. - * - * @retval NRF_SUCCESS If the pointer to the data was retrieved successfully. - * @retval NRF_ERROR_INVALID_PARAM If either @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If data was not found in flash. - */ -ret_code_t pdb_peer_data_ptr_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_flash_t * const p_peer_data); - - -/**@brief Function for retrieving pointers to a write buffer for peer data. - * - * @details This function will provide pointers to a buffer of the data. The data buffer will not be - * written to persistent storage until @ref pdb_write_buf_store is called. The buffer is - * released by calling either @ref pdb_write_buf_release, @ref pdb_write_buf_store, or - * @ref pdb_peer_free. - * - * When the data_id refers to a variable length data type, the available size is written - * to the data, both the top-level, and any internal length fields. - * - * @note Calling this function on a peer_id/data_id pair that already has a buffer created will - * give the same buffer, not create a new one. If n_bufs was increased since last time, the - * buffer might be relocated to be able to provide additional room. In this case, the data - * will be copied. If n_bufs was increased since last time, this function might return @ref - * NRF_ERROR_BUSY. In that case, the buffer is automatically released. - * - * @param[in] peer_id ID of peer to get a write buffer for. - * @param[in] data_id Which piece of data to get. - * @param[in] n_bufs The number of contiguous buffers needed. - * @param[out] p_peer_data Pointers to mutable peer data. - * - * @retval NRF_SUCCESS Data retrieved successfully. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated, or n_bufs was 0 - * or more than the total available buffers. - * @retval NRF_ERROR_NULL p_peer_data was NULL. - * @retval NRF_ERROR_BUSY Not enough buffer(s) available. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - uint32_t n_bufs, - pm_peer_data_t * p_peer_data); - - -/**@brief Function for freeing a write buffer allocated with @ref pdb_write_buf_get. - * - * @note This function will not write peer data to persistent memory. Data in released buffer will - * be lost. - * - * @note This function will undo any previous call to @ref pdb_write_buf_store_prepare for this - * piece of data. - * - * @param[in] peer_id ID of peer to release buffer for. - * @param[in] data_id Which piece of data to release buffer for. - * - * @retval NRF_SUCCESS Successfully released buffer. - * @retval NRF_ERROR_NOT_FOUND No buffer was allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for reserving space in persistent storage for data in a buffer. - * - * @note This function only works for data which has a write buffer allocated. If the write buffer - * is released, this prepare is undone. - * - * @note If space has already been reserved for this data, nothing is done. - * - * @param[in] peer_id The peer whose data to reserve space for. - * @param[in] data_id The type of data to reserve space for. - * - * @retval NRF_SUCCESS Successfully reserved space in persistent storage. - * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. - * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - */ -ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for writing data into persistent storage. Writing happens asynchronously. - * - * @note This will unlock the data after it has been written. - * - * @param[in] peer_id The ID used to address the write buffer. - * @param[in] data_id Which piece of data to store. - * @param[in] new_peer_id The ID to put in flash. This will usually be the same as peer_id. - * - * @retval NRF_SUCCESS Data storing was successfully started. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. Please clear some - * space, the operation will be reattempted after the next compress - * procedure. This error will not happen if - * @ref pdb_write_buf_store_prepare is called beforehand. - * @retval NRF_ERROR_INVALID_PARAM Data ID was invalid. - * @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair. - * @retval NRF_ERROR_INTERNAL Unexpected internal error. - */ -ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_id_t new_peer_id); - - -/**@brief Function for clearing data from persistent storage. - * - * @param[in] peer_id ID of peer to clear data for. - * @param[in] data_id Which piece of data to clear. - * - * @retval NRF_SUCCESS The clear was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM Data ID or peer ID was invalid. - * @retval NRF_ERROR_NOT_FOUND Nothing to clear for this peer ID/data ID combination. - * @retval NRF_ERROR_BUSY Underlying modules are busy and can't take any more requests at - * this moment. - * @retval NRF_ERROR_INTERNAL Internal error. - */ -ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pdb_n_peers(void); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. - */ -pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs pending deletion. - * Can be used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID pending deletion. - * @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID. - */ -pm_peer_id_t pdb_next_deleted_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for copy peer data from flash into a provided buffer. - * - * @param[in] peer_id The peer the data belongs to. - * @param[in] data_id The data to read. - * @param[inout] p_peer_data The buffer where to copy data into. The field @c length_words in this - * parameter must represent the buffer length in words. - * - * @note Actually, it represents the buffer length in bytes upon entering the function, - * and upon exit it represents the length of the data in words.. not good. Fix this. - * - * @retval NRF_SUCCESS If the operation was successful. - * @retval NRF_ERROR_INVALID_PARAM If @p peer_id or @p data_id are invalid. - * @retval NRF_ERROR_NOT_FOUND If the data was not found in flash. - * @retval NRF_ERROR_NO_MEM If the provided buffer is too small. - */ -ret_code_t pdb_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - pm_peer_data_t * const p_peer_data); - - -/**@brief Function for writing data directly to persistent storage from external memory. - * - * @param[in] peer_id ID of peer to write data for. - * @param[in] p_peer_data Data to store. - * @param[out] p_store_token A token identifying this particular store operation. The token can be - * used to identify events pertaining to this operation. - * - * @retval NRF_SUCCESS Data successfully written. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - * @retval NRF_ERROR_NULL p_peer_data contained a NULL pointer. - * @retval NRF_ERROR_STORAGE_FULL No space available in persistent storage. - * @retval NRF_ERROR_INVALID_LENGTH Data length above the maximum allowed. - * @retval NRF_ERROR_BUSY Unable to perform operation at this time. - */ -ret_code_t pdb_raw_store(pm_peer_id_t peer_id, - pm_peer_data_const_t * p_peer_data, - pm_store_token_t * p_store_token); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_DATABASE_H__ */ - - diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c deleted file mode 100644 index 06b0594c71..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.c +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "peer_id.h" - -#include -#include -#include "sdk_errors.h" -#include "peer_manager_types.h" -#include "pm_mutex.h" - - -typedef struct -{ - uint8_t used_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are in use. */ - uint8_t deleted_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are marked for deletion. */ -} pi_t; - - -static pi_t m_pi = {{0}, {0}}; - - -static void internal_state_reset(pi_t * p_pi) -{ - memset(p_pi, 0, sizeof(pi_t)); -} - - -void peer_id_init(void) -{ - internal_state_reset(&m_pi); - pm_mutex_init(m_pi.used_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); - pm_mutex_init(m_pi.deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS); -} - - -static pm_peer_id_t claim(pm_peer_id_t peer_id, uint8_t * mutex_group) -{ - pm_peer_id_t allocated_peer_id = PM_PEER_ID_INVALID; - if (peer_id == PM_PEER_ID_INVALID) - { - allocated_peer_id = pm_mutex_lock_first_available(mutex_group, PM_PEER_ID_N_AVAILABLE_IDS); - if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS) - { - allocated_peer_id = PM_PEER_ID_INVALID; - } - } - else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - bool lock_success = pm_mutex_lock(mutex_group, peer_id); - allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID; - } - return allocated_peer_id; -} - - -static void release(pm_peer_id_t peer_id, uint8_t * mutex_group) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - pm_mutex_unlock(mutex_group, peer_id); - } -} - - -pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id) -{ - return claim(peer_id, m_pi.used_peer_ids); -} - - -bool peer_id_delete(pm_peer_id_t peer_id) -{ - pm_peer_id_t deleted_peer_id; - - if (peer_id == PM_PEER_ID_INVALID) - { - return false; - } - - deleted_peer_id = claim(peer_id, m_pi.deleted_peer_ids); - - return (deleted_peer_id == peer_id); -} - - -void peer_id_free(pm_peer_id_t peer_id) -{ - release(peer_id, m_pi.used_peer_ids); - release(peer_id, m_pi.deleted_peer_ids); -} - - -bool peer_id_is_allocated(pm_peer_id_t peer_id) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - return pm_mutex_lock_status_get(m_pi.used_peer_ids, peer_id); - } - return false; -} - - -bool peer_id_is_deleted(pm_peer_id_t peer_id) -{ - if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS) - { - return pm_mutex_lock_status_get(m_pi.deleted_peer_ids, peer_id); - } - return false; -} - - -pm_peer_id_t next_id_get(pm_peer_id_t prev_peer_id, uint8_t * mutex_group) -{ - pm_peer_id_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1); - for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) - { - if (pm_mutex_lock_status_get(mutex_group, i)) - { - return i; - } - } - - return PM_PEER_ID_INVALID; -} - - -pm_peer_id_t peer_id_get_next_used(pm_peer_id_t peer_id) -{ - peer_id = next_id_get(peer_id, m_pi.used_peer_ids); - - while (peer_id != PM_PEER_ID_INVALID) - { - if (!peer_id_is_deleted(peer_id)) - { - return peer_id; - } - - peer_id = next_id_get(peer_id, m_pi.used_peer_ids); - } - - return peer_id; -} - - -pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id) -{ - return next_id_get(prev_peer_id, m_pi.deleted_peer_ids); -} - - -uint32_t peer_id_n_ids(void) -{ - uint32_t n_ids = 0; - - for (pm_peer_id_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++) - { - n_ids += pm_mutex_lock_status_get(m_pi.used_peer_ids, i); - } - - return n_ids; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h deleted file mode 100644 index 5664ccc574..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_id.h +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_ID_H__ -#define PEER_ID_H__ - - -#include -#include "sdk_errors.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup peer_id Peer IDs - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module keeps track of which peer IDs are in - * use and which are free. - */ - - -/**@brief Function for initializing the module. - */ -void peer_id_init(void); - - -/**@brief Function for claiming an unused peer ID. - * - * @param peer_id The peer ID to allocate. If this is @ref PM_PEER_ID_INVALID, the first available - * will be allocated. - * - * @return The allocated peer ID. - * @retval PM_PEER_ID_INVALID If no peer ID could be allocated or module is not initialized. - */ -pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id); - - -/**@brief Function for marking a peer ID for deletion. - * - * @param peer_id The peer ID to delete. - * - * @retval true Deletion was successful. - * @retval false Peer ID already marked for deletion, peer_id was PM_PEER_ID_INVALID, or module is - * not initialized. - */ -bool peer_id_delete(pm_peer_id_t peer_id); - - -/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent - * storage. - * - * @param[in] peer_id Peer ID to free. - */ -void peer_id_free(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is marked for deletion. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true peer_id is in marked for deletion. - * @retval false peer_id is not marked for deletion, or the module is not initialized. - */ -bool peer_id_is_deleted(pm_peer_id_t peer_id); - - -/**@brief Function for finding out whether a peer ID is in use. - * - * @param[in] peer_id The peer ID to inquire about. - * - * @retval true peer_id is in use. - * @retval false peer_id is free, or the module is not initialized. - */ -bool peer_id_is_allocated(pm_peer_id_t peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be - * used to loop through all used peer IDs. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is - * not initialized. - */ -pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all peer IDs marked for deletion. - * Can be used to loop through all peer IDs marked for deletion. - * - * @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary - * peer ID. - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. - * @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID. - * @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is - * not initialized. - */ -pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers - * in persistent storage. - * - * @return The number of valid peer IDs, or 0 if module is not initialized. - */ -uint32_t peer_id_n_ids(void); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_ID_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c deleted file mode 100644 index 9d31a463ca..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.c +++ /dev/null @@ -1,965 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "ble_err.h" -#include "peer_manager.h" -#include -#include "security_manager.h" -#include "security_dispatcher.h" -#include "gatt_cache_manager.h" -#include "gatts_cache_manager.h" -#include "peer_database.h" -#include "peer_data_storage.h" -#include "id_manager.h" -#include "ble_conn_state.h" -#include "peer_manager_internal.h" -#include "nrf_sdh_ble.h" - - -#define MODULE_INITIALIZED (m_module_initialized) /**< Macro indicating whether the module has been initialized properly. */ - - -static bool m_module_initialized; /**< Whether or not @ref pm_init has been called successfully. */ -static bool m_peer_rank_initialized; /**< Whether or not @ref rank_init has been called successfully. */ -static bool m_deleting_all; /**< True from when @ref pm_peers_delete is called until all peers have been deleted. */ -static pm_store_token_t m_peer_rank_token; /**< The store token of an ongoing peer rank update via a call to @ref pm_peer_rank_highest. If @ref PM_STORE_TOKEN_INVALID, there is no ongoing update. */ -static uint32_t m_current_highest_peer_rank; /**< The current highest peer rank. Used by @ref pm_peer_rank_highest. */ -static pm_peer_id_t m_highest_ranked_peer; /**< The peer with the highest peer rank. Used by @ref pm_peer_rank_highest. */ -static pm_evt_handler_t m_evt_handlers[PM_MAX_REGISTRANTS];/**< The subscribers to Peer Manager events, as registered through @ref pm_register. */ -static uint8_t m_n_registrants; /**< The number of event handlers registered through @ref pm_register. */ -static ble_conn_state_user_flag_id_t m_bonded_flag_id; /**< The flag ID for which connections are with a peer with which we are bonded. */ - - -/**@brief Function for sending a Peer Manager event to all subscribers. - * - * @param[in] p_pm_evt The event to send. - */ -static void evt_send(pm_evt_t const * p_pm_evt) -{ - for (int i = 0; i < m_n_registrants; i++) - { - m_evt_handlers[i](p_pm_evt); - } -} - - -/**@brief Function for initializing peer rank static variables. - */ -static void rank_vars_update(void) -{ - ret_code_t err_code = pm_peer_ranks_get(&m_highest_ranked_peer, - &m_current_highest_peer_rank, - NULL, - NULL); - - m_peer_rank_initialized = ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)); -} - - -/**@brief Event handler for events from the Peer Database module. - * This handler is extern in the Peer Database module. - * - * @param[in] p_pdb_evt The incoming Peer Database event. - */ -void pm_pdb_evt_handler(pm_evt_t * p_pdb_evt) -{ - bool send_evt = true; - - p_pdb_evt->conn_handle = im_conn_handle_get(p_pdb_evt->peer_id); - - switch (p_pdb_evt->evt_id) - { - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) - && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_succeeded.token)) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_highest_ranked_peer = p_pdb_evt->peer_id; - - p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - } - else if ( m_peer_rank_initialized - && (p_pdb_evt->peer_id == m_highest_ranked_peer) - && (p_pdb_evt->params.peer_data_update_succeeded.data_id - == PM_PEER_DATA_ID_PEER_RANK)) - { - // Update peer rank variable if highest ranked peer has changed its rank. - rank_vars_update(); - } - } - else if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_DELETE) - { - if ( m_peer_rank_initialized - && (p_pdb_evt->peer_id == m_highest_ranked_peer) - && (p_pdb_evt->params.peer_data_update_succeeded.data_id == PM_PEER_DATA_ID_PEER_RANK)) - { - // Update peer rank variable if highest ranked peer has deleted its rank. - rank_vars_update(); - } - } - break; - - case PM_EVT_PEER_DATA_UPDATE_FAILED: - if (p_pdb_evt->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE) - { - if ( (m_peer_rank_token != PM_STORE_TOKEN_INVALID) - && (m_peer_rank_token == p_pdb_evt->params.peer_data_update_failed.token)) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_current_highest_peer_rank -= 1; - - p_pdb_evt->params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - } - } - break; - - case PM_EVT_PEER_DELETE_SUCCEEDED: - // Check that no peers marked for deletion are left. - if (m_deleting_all - && (pdb_next_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID) - && (pdb_next_deleted_peer_id_get(PM_PEER_ID_INVALID) == PM_PEER_ID_INVALID)) - { - // pm_peers_delete() has been called and this is the last peer to be deleted. - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - - send_evt = false; - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); // Ensure that PEER_DELETE_SUCCEEDED arrives before PEERS_DELETE_SUCCEEDED. - evt_send(&pm_delete_all_evt); - } - - if (m_peer_rank_initialized && (p_pdb_evt->peer_id == m_highest_ranked_peer)) - { - // Update peer rank variable if highest ranked peer has been deleted. - rank_vars_update(); - } - break; - - case PM_EVT_PEER_DELETE_FAILED: - if (m_deleting_all) - { - // pm_peers_delete() was called and has thus failed. - - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_FAILED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - pm_delete_all_evt.params.peers_delete_failed_evt.error - = p_pdb_evt->params.peer_delete_failed.error; - - send_evt = false; - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); // Ensure that PEER_DELETE_FAILED arrives before PEERS_DELETE_FAILED. - evt_send(&pm_delete_all_evt); - } - break; - - default: - // Do nothing. - break; - } - - if (send_evt) - { - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_pdb_evt); - } -} - - -/**@brief Event handler for events from the Security Manager module. - * This handler is extern in the Security Manager module. - * - * @param[in] p_sm_evt The incoming Security Manager event. - */ -void pm_sm_evt_handler(pm_evt_t * p_sm_evt) -{ - VERIFY_PARAM_NOT_NULL_VOID(p_sm_evt); - - switch (p_sm_evt->evt_id) - { - case PM_EVT_CONN_SEC_SUCCEEDED: - { - bool bonded = p_sm_evt->params.conn_sec_succeeded.procedure - == PM_LINK_SECURED_PROCEDURE_BONDING; - ble_conn_state_user_flag_set(p_sm_evt->conn_handle, m_bonded_flag_id, bonded); - break; - } - - default: - /* No action */ - break; - } - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_sm_evt); -} - - -/**@brief Event handler for events from the GATT Cache Manager module. - * This handler is extern in GATT Cache Manager. - * - * @param[in] p_gcm_evt The incoming GATT Cache Manager event. - */ -void pm_gcm_evt_handler(pm_evt_t * p_gcm_evt) -{ - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_gcm_evt); -} - - -/**@brief Event handler for events from the ID Manager module. - * This function is registered in the ID Manager. - * - * @param[in] p_im_evt The incoming ID Manager event. - */ -void pm_im_evt_handler(pm_evt_t * p_im_evt) -{ - switch (p_im_evt->evt_id) - { - case PM_EVT_BONDED_PEER_CONNECTED: - ble_conn_state_user_flag_set(p_im_evt->conn_handle, m_bonded_flag_id, true); - break; - default: - /* No action. */ - break; - } - - // Forward the event to all registered Peer Manager event handlers. - evt_send(p_im_evt); -} - -/** - * @brief Function for handling BLE events. - * - * @param[in] p_ble_evt Event received from the BLE stack. - * @param[in] p_context Context. - */ -static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) -{ - VERIFY_MODULE_INITIALIZED_VOID(); - - im_ble_evt_handler(p_ble_evt); - sm_ble_evt_handler(p_ble_evt); - gcm_ble_evt_handler(p_ble_evt); -} - -NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, PM_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); - - -/**@brief Function for resetting the internal state of this module. - */ -static void internal_state_reset() -{ - m_highest_ranked_peer = PM_PEER_ID_INVALID; - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_bonded_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID; -} - - -ret_code_t pm_init(void) -{ - ret_code_t err_code; - - err_code = pds_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = pdb_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = sm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = smd_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = gcm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = gscm_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - err_code = im_init(); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - internal_state_reset(); - - m_bonded_flag_id = ble_conn_state_user_flag_acquire(); - if (m_bonded_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - m_peer_rank_initialized = false; - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -ret_code_t pm_register(pm_evt_handler_t event_handler) -{ - VERIFY_MODULE_INITIALIZED(); - - if (m_n_registrants >= PM_MAX_REGISTRANTS) - { - return NRF_ERROR_NO_MEM; - } - - m_evt_handlers[m_n_registrants] = event_handler; - m_n_registrants += 1; - - return NRF_SUCCESS; -} - - -ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - - err_code = sm_sec_params_set(p_sec_params); - - // NRF_ERROR_INVALID_PARAM if parameters are invalid, - // NRF_SUCCESS otherwise. - return err_code; -} - - -ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - - err_code = sm_link_secure(conn_handle, force_repairing); - - return err_code; -} - - -void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - if (p_conn_sec_config != NULL) - { - sm_conn_sec_config_reply(conn_handle, p_conn_sec_config); - } -} - - -ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context) -{ - VERIFY_MODULE_INITIALIZED(); - - return sm_sec_params_reply(conn_handle, p_sec_params, p_context); -} - - -void pm_local_database_has_changed(void) -{ - VERIFY_MODULE_INITIALIZED_VOID(); - gcm_local_database_has_changed(); -} - - -ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr) -{ - VERIFY_MODULE_INITIALIZED(); - return im_id_addr_set(p_addr); -} - - -ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_addr); - return im_id_addr_get(p_addr); -} - - -ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_privacy_params); - return im_privacy_set(p_privacy_params); -} - - -ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_privacy_params); - VERIFY_PARAM_NOT_NULL(p_privacy_params->p_device_irk); - return im_privacy_get(p_privacy_params); -} - - -bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk) -{ - VERIFY_MODULE_INITIALIZED(); - - if ((p_addr == NULL) || (p_irk == NULL)) - { - return false; - } - else - { - return im_address_resolve(p_addr, p_irk); - } -} - - -ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - return im_whitelist_set(p_peers, peer_cnt); -} - - -ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - - if (((p_addrs == NULL) && (p_irks == NULL)) || - ((p_addrs != NULL) && (p_addr_cnt == NULL)) || - ((p_irks != NULL) && (p_irk_cnt == NULL))) - { - // The buffers can't be both NULL, and if a buffer is provided its size must be specified. - return NRF_ERROR_NULL; - } - - return im_whitelist_get(p_addrs, p_addr_cnt, p_irks, p_irk_cnt); -} - - -ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt) -{ - VERIFY_MODULE_INITIALIZED(); - return im_device_identities_list_set(p_peers, peer_cnt); -} - - -ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_conn_sec_status); - - ble_conn_state_status_t status = ble_conn_state_status(conn_handle); - - if (status == BLE_CONN_STATUS_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - - p_conn_sec_status->connected = (status == BLE_CONN_STATUS_CONNECTED); - p_conn_sec_status->bonded = ble_conn_state_user_flag_get(conn_handle, m_bonded_flag_id); - p_conn_sec_status->encrypted = ble_conn_state_encrypted(conn_handle); - p_conn_sec_status->mitm_protected = ble_conn_state_mitm_protected(conn_handle); - return NRF_SUCCESS; -} - - -ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) -{ - VERIFY_MODULE_INITIALIZED(); - return sm_lesc_public_key_set(p_public_key); -} - - -ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_conn_handle); - *p_conn_handle = im_conn_handle_get(peer_id); - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_peer_id); - *p_peer_id = im_peer_id_get_by_conn_handle(conn_handle); - return NRF_SUCCESS; -} - - -uint32_t pm_peer_count(void) -{ - if (!MODULE_INITIALIZED) - { - return 0; - } - return pdb_n_peers(); -} - - -pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id) -{ - if (!MODULE_INITIALIZED) - { - return PM_PEER_ID_INVALID; - } - return pdb_next_peer_id_get(prev_peer_id); -} - - -ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void * p_data, - uint16_t * p_length) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_data); - VERIFY_PARAM_NOT_NULL(p_length); - if (ALIGN_NUM(4, *p_length) != *p_length) - { - return NRF_ERROR_INVALID_PARAM; - } - - pm_peer_data_t peer_data; - memset(&peer_data, 0, sizeof(peer_data)); - peer_data.length_words = BYTES_TO_WORDS(*p_length); - peer_data.data_id = data_id; - peer_data.p_all_data = p_data; - - ret_code_t err_code = pdb_peer_data_load(peer_id, data_id, &peer_data); - - *p_length = peer_data.length_words * BYTES_PER_WORD; - - return err_code; -} - - -ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, - pm_peer_data_bonding_t * p_data) -{ - uint16_t length = sizeof(pm_peer_data_bonding_t); - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_BONDING, - p_data, - &length); -} - - -ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, - ble_gatt_db_srv_t * p_data, - uint16_t * p_length) -{ - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_GATT_REMOTE, - p_data, - p_length); -} - - -ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, - void * p_data, - uint16_t * p_length) -{ - return pm_peer_data_load(peer_id, - PM_PEER_DATA_ID_APPLICATION, - p_data, - p_length); -} - - -ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_data); - if (ALIGN_NUM(4, length) != length) - { - return NRF_ERROR_INVALID_PARAM; - } - - pm_peer_data_flash_t peer_data; - memset(&peer_data, 0, sizeof(peer_data)); - peer_data.length_words = BYTES_TO_WORDS(length); - peer_data.data_id = data_id; - peer_data.p_all_data = p_data; - - return pdb_raw_store(peer_id, &peer_data, p_token); -} - - -ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, - pm_peer_data_bonding_t const * p_data, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_BONDING, - p_data, - ALIGN_NUM(4, sizeof(pm_peer_data_bonding_t)), - p_token); -} - - -ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, - ble_gatt_db_srv_t const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_GATT_REMOTE, - p_data, - length, - p_token); -} - - -ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, - void const * p_data, - uint16_t length, - pm_store_token_t * p_token) -{ - return pm_peer_data_store(peer_id, - PM_PEER_DATA_ID_APPLICATION, - p_data, - length, - p_token); -} - - -ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id) -{ - VERIFY_MODULE_INITIALIZED(); - - if (data_id == PM_PEER_DATA_ID_BONDING) - { - return NRF_ERROR_INVALID_PARAM; - } - - return pdb_clear(peer_id, data_id); -} - - -ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, - pm_peer_data_bonding_t * p_bonding_data, - pm_store_token_t * p_token) -{ - ret_code_t err_code; - pm_peer_id_t peer_id; - pm_peer_data_flash_t peer_data; - - VERIFY_MODULE_INITIALIZED(); - VERIFY_PARAM_NOT_NULL(p_bonding_data); - VERIFY_PARAM_NOT_NULL(p_new_peer_id); - - memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); - - // Search through existing bonds to look for a duplicate. - pds_peer_data_iterate_prepare(); - - // @note emdi: should maybe use a critical section, since data is not copied while iterating. - while (pds_peer_data_iterate(PM_PEER_DATA_ID_BONDING, &peer_id, &peer_data)) - { - if (im_is_duplicate_bonding_data(p_bonding_data, peer_data.p_bonding_data)) - { - *p_new_peer_id = peer_id; - return NRF_SUCCESS; - } - } - - // If no duplicate data is found, prepare to write a new bond to flash. - - *p_new_peer_id = pdb_peer_allocate(); - - if (*p_new_peer_id == PM_PEER_ID_INVALID) - { - return NRF_ERROR_NO_MEM; - } - - memset(&peer_data, 0, sizeof(pm_peer_data_flash_t)); - - peer_data.data_id = PM_PEER_DATA_ID_BONDING; - peer_data.p_bonding_data = p_bonding_data; - peer_data.length_words = BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)); - - err_code = pdb_raw_store(*p_new_peer_id, &peer_data, p_token); - - if (err_code != NRF_SUCCESS) - { - if (im_peer_free(*p_new_peer_id) != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - // NRF_ERROR_STORAGE_FULL, if no space in flash. - // NRF_ERROR_BUSY, if flash filesystem was busy. - // NRF_ERROR_INTENRAL, on internal error. - return err_code; - } - - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_delete(pm_peer_id_t peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - - return im_peer_free(peer_id); -} - - -ret_code_t pm_peers_delete(void) -{ - VERIFY_MODULE_INITIALIZED(); - - m_deleting_all = true; - - pm_peer_id_t current_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - - if (current_peer_id == PM_PEER_ID_INVALID) - { - // No peers bonded. - m_deleting_all = false; - - pm_evt_t pm_delete_all_evt; - memset(&pm_delete_all_evt, 0, sizeof(pm_evt_t)); - pm_delete_all_evt.evt_id = PM_EVT_PEERS_DELETE_SUCCEEDED; - pm_delete_all_evt.peer_id = PM_PEER_ID_INVALID; - pm_delete_all_evt.conn_handle = BLE_CONN_HANDLE_INVALID; - - evt_send(&pm_delete_all_evt); - } - - while (current_peer_id != PM_PEER_ID_INVALID) - { - ret_code_t err_code = pm_peer_delete(current_peer_id); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - current_peer_id = pdb_next_peer_id_get(current_peer_id); - } - - return NRF_SUCCESS; -} - - -ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, - uint32_t * p_highest_rank, - pm_peer_id_t * p_lowest_ranked_peer, - uint32_t * p_lowest_rank) -{ - VERIFY_MODULE_INITIALIZED(); - - pm_peer_id_t peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID); - uint32_t peer_rank = 0; - //lint -save -e65 -e64 - pm_peer_data_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(peer_rank)), - .p_peer_rank = &peer_rank}; - //lint -restore - ret_code_t err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); - uint32_t highest_rank = 0; - uint32_t lowest_rank = 0xFFFFFFFF; - pm_peer_id_t highest_ranked_peer = PM_PEER_ID_INVALID; - pm_peer_id_t lowest_ranked_peer = PM_PEER_ID_INVALID; - - if (err_code == NRF_ERROR_INVALID_PARAM) - { - // No peer IDs exist. - return NRF_ERROR_NOT_FOUND; - } - - while ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND)) - { - if (err_code == NRF_ERROR_NOT_FOUND) - { - peer_rank = 0; - } - if (peer_rank >= highest_rank) - { - highest_rank = peer_rank; - highest_ranked_peer = peer_id; - } - if (peer_rank < lowest_rank) - { - lowest_rank = peer_rank; - lowest_ranked_peer = peer_id; - } - peer_id = pdb_next_peer_id_get(peer_id); - err_code = pdb_peer_data_load(peer_id, PM_PEER_DATA_ID_PEER_RANK, &peer_data); - } - if (peer_id == PM_PEER_ID_INVALID) - { - err_code = NRF_SUCCESS; - if (p_highest_ranked_peer != NULL) - { - *p_highest_ranked_peer = highest_ranked_peer; - } - if (p_highest_rank != NULL) - { - *p_highest_rank = highest_rank; - } - if (p_lowest_ranked_peer != NULL) - { - *p_lowest_ranked_peer = lowest_ranked_peer; - } - if (p_lowest_rank != NULL) - { - *p_lowest_rank = lowest_rank; - } - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - return err_code; -} - - -/**@brief Function for initializing peer rank functionality. - */ -static void rank_init(void) -{ - rank_vars_update(); -} - - -ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id) -{ - VERIFY_MODULE_INITIALIZED(); - - ret_code_t err_code; - //lint -save -e65 -e64 - pm_peer_data_flash_t peer_data = {.length_words = BYTES_TO_WORDS(sizeof(m_current_highest_peer_rank)), - .data_id = PM_PEER_DATA_ID_PEER_RANK, - .p_peer_rank = &m_current_highest_peer_rank}; - //lint -restore - - - if (!m_peer_rank_initialized) - { - rank_init(); - } - - if (!m_peer_rank_initialized || (m_peer_rank_token != PM_STORE_TOKEN_INVALID)) - { - err_code = NRF_ERROR_BUSY; - } - else - { - if ((peer_id == m_highest_ranked_peer) && (m_current_highest_peer_rank > 0)) - { - pm_evt_t pm_evt; - - // The reported peer is already regarded as highest (provided it has an index at all) - err_code = NRF_SUCCESS; - - memset(&pm_evt, 0, sizeof(pm_evt)); - pm_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED; - pm_evt.conn_handle = im_conn_handle_get(peer_id); - pm_evt.peer_id = peer_id; - pm_evt.params.peer_data_update_succeeded.data_id = PM_PEER_DATA_ID_PEER_RANK; - pm_evt.params.peer_data_update_succeeded.action = PM_PEER_DATA_OP_UPDATE; - pm_evt.params.peer_data_update_succeeded.token = PM_STORE_TOKEN_INVALID; - pm_evt.params.peer_data_update_succeeded.flash_changed = false; - - evt_send(&pm_evt); - } - else - { - m_current_highest_peer_rank += 1; - err_code = pdb_raw_store(peer_id, &peer_data, &m_peer_rank_token); - if (err_code != NRF_SUCCESS) - { - m_peer_rank_token = PM_STORE_TOKEN_INVALID; - m_current_highest_peer_rank -= 1; - { - if ((err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_STORAGE_FULL)) - err_code = NRF_ERROR_INTERNAL; - } - } - } - } - return err_code; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h deleted file mode 100644 index b8a65f098f..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager.h +++ /dev/null @@ -1,765 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file peer_manager.h - * - * @defgroup peer_manager Peer Manager - * @ingroup ble_sdk_lib - * @{ - * @brief Module for managing BLE bonding, which includes controlling encryption and pairing - * procedures as well as persistently storing different pieces of data that must be stored - * when bonded. - * - * @details The API consists of functions for configuring the pairing and encryption behavior of the - * device and functions for manipulating the stored data. - * - * This module uses Flash Data Storage (FDS) to interface with persistent storage. The - * Peer Manager needs exclusive use of certain FDS file IDs and record keys. See - * @ref lib_fds_functionality_keys for more information. - */ - - -#ifndef PEER_MANAGER_H__ -#define PEER_MANAGER_H__ - -#include -#include -#include "sdk_common.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "peer_database.h" - -#ifdef __cplusplus -extern "C" { -#endif - - - -/**@brief Security status of a connection. - */ -typedef struct -{ - uint8_t connected : 1; /**< @brief The connection is active (not disconnected). */ - uint8_t encrypted : 1; /**< @brief Communication on this link is encrypted. */ - uint8_t mitm_protected : 1; /**< @brief The encrypted communication is also protected against man-in-the-middle attacks. */ - uint8_t bonded : 1; /**< @brief The peer is bonded with us. */ -} pm_conn_sec_status_t; - - -/**@brief Function for initializing the Peer Manager. - * - * @details You must initialize the Peer Manager before you can call any other Peer Manager - * functions. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_init(void); - - -/**@brief Function for registering an event handler with the Peer Manager. - * - * @param[in] event_handler Callback for events from the @ref peer_manager module. @p event_handler - * is called for every event that the Peer Manager sends after this - * function is called. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_NULL If @p event_handler was NULL. - * @retval NRF_ERROR_NO_MEM If no more registrations can happen. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_register(pm_evt_handler_t event_handler); - - -/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. - * - * @details Until this function is called, all bonding procedures that are initiated by the - * peer are rejected. - * - * This function can be called multiple times with different parameters, even with NULL as - * @p p_sec_params, in which case the Peer Manager starts rejecting all procedures again. - * - * @param[in] p_sec_params Security parameters to be used for subsequent security procedures. - * - * @retval NRF_SUCCESS If the parameters were set successfully. - * @retval NRF_ERROR_INVALID_PARAM If the combination of parameters is invalid. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params); - - -/**@brief Function for establishing encryption on a connection, and optionally establishing a bond. - * - * @details This function attempts to secure the link that is specified by @p conn_handle. It uses - * the parameters that were previously provided in a call to @ref pm_sec_params_set. - * - * If the connection is a master connection, calling this function starts a security - * procedure on the link. If we have keys from a previous bonding procedure with this peer - * and the keys meet the security requirements in the currently active security parameters, - * the function attempts to establish encryption with the existing keys. If no key exists, - * the function attempts to perform pairing and bonding according to the currently active - * security parameters. - * - * If the function completes successfully, a @ref PM_EVT_CONN_SEC_START event is sent. - * The procedure might be queued, in which case the @ref PM_EVT_CONN_SEC_START event is - * delayed until the procedure is initiated in the SoftDevice. - * - * If the connection is a slave connection, the function sends a security request to - * the peer (master). It is up to the peer then to initiate pairing or encryption. - * If the peer ignores the request, a @ref BLE_GAP_EVT_TIMEOUT event occurs - * with the source @ref BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST. Otherwise, the peer initiates - * security, in which case things happen as if the peer had initiated security itself. - * See @ref PM_EVT_CONN_SEC_START for information about peer-initiated security. - * - * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. - * @param[in] force_repairing Whether to force a pairing procedure even if there is an existing - * encryption key. This argument is relevant only for - * the central role. Recommended value: false. - * - * @retval NRF_SUCCESS If the operation completed successfully. - * @retval NRF_ERROR_TIMEOUT If there was an SMP time-out, so that no more security - * operations can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. - * @retval NRF_ERROR_NOT_FOUND If the security parameters have not been set, either by - * @ref pm_sec_params_set or by @ref pm_conn_sec_params_reply. - * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. - * @retval NRF_ERROR_NO_MEM If no more authentication procedures can run in parallel - * for the given role. See @ref sd_ble_gap_authenticate. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized, or the peer is - * disconnected or in the process of disconnecting. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing security parameters for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, the parameters given in @ref pm_sec_params_set are used. See @ref - * pm_conn_sec_config_t for the value of the default. - * - * @param[in] conn_handle The connection to set the parameters for. - * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. - * @param[in] p_context The context found in the request event that this function replies to. - * - * @retval NRF_SUCCESS Successful reply. - * @retval NRF_ERROR_NULL p_sec_params or p_context was null. - * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t pm_conn_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context); - - -/**@brief Function for manually informing that the local database has changed. - * - * @details This function sends a service changed indication to all bonded and/or connected peers - * that subscribe to this indication. If a bonded peer is not connected, the indication is - * sent when it reconnects. Every time an indication is sent, a @ref - * PM_EVT_SERVICE_CHANGED_IND_SENT event occurs, followed by a @ref - * PM_EVT_SERVICE_CHANGED_IND_CONFIRMED when the peer sends its confirmation. Peers that - * are not subscribed to the service changed indication when this function is called do not - * receive an indication, and no events are sent to the user. Likewise, if the service - * changed characteristic is not present in the local database, this no indications are - * sent peers, and no events are sent to the user. - */ -void pm_local_database_has_changed(void); - - -/**@brief Function for getting the security status of a connection. - * - * @param[in] conn_handle Connection handle of the link as provided by the SoftDevice. - * @param[out] p_conn_sec_status Security status of the link. - * - * @retval NRF_SUCCESS If pairing was initiated successfully. - * @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid. - * @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status); - - -/**@brief Experimental function for specifying the public key to use for LESC operations. - * - * @details This function can be called multiple times. The specified public key will be used for - * all subsequent LESC (LE Secure Connections) operations until the next time this function - * is called. - * - * @note The key must continue to reside in application memory as it is not copied by Peer Manager. - * - * @param[in] p_public_key The public key to use for all subsequent LESC operations. - * - * @retval NRF_SUCCESS If pairing was initiated successfully. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); - - -/**@brief Function for setting or clearing the whitelist. - * - * When using the S13x SoftDevice v3.x, this function sets or clears the whitelist. - * When using the S13x SoftDevice v2.x, this function caches a list of - * peers that can be retrieved later by @ref pm_whitelist_get to pass to the @ref lib_ble_advertising. - * - * To clear the current whitelist, pass either NULL as @p p_peers or zero as @p peer_cnt. - * - * @param[in] p_peers The peers to add to the whitelist. Pass NULL to clear the current whitelist. - * @param[in] peer_cnt The number of peers to add to the whitelist. The number must not be greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. Pass zero to clear the current - * whitelist. - * - * @retval NRF_SUCCESS If the whitelist was successfully set or cleared. - * @retval BLE_GAP_ERROR_WHITELIST_IN_USE If a whitelist is already in use and cannot be set. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer in @p p_peers has an address that cannot - * be used for whitelisting. - * @retval NRF_ERROR_NOT_FOUND If any of the peers in @p p_peers cannot be found. - * @retval NRF_ERROR_DATA_SIZE If @p peer_cnt is greater than - * @ref BLE_GAP_WHITELIST_ADDR_MAX_COUNT. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_whitelist_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/**@brief Function for retrieving the previously set whitelist. - * - * The function retrieves the whitelist of GAP addresses and IRKs that was - * previously set by @ref pm_whitelist_set. - * - * To retrieve only GAP addresses or only IRKs, provide only one of the - * buffers. If a buffer is provided, its size must be specified. - * - * @param[out] p_addrs The buffer where to store GAP addresses. Pass NULL to retrieve - * only IRKs (in that case, @p p_irks must not be NULL). - * @param[in,out] p_addr_cnt In: The size of the @p p_addrs buffer. - * May be NULL if and only if @p p_addrs is NULL. - * Out: The number of GAP addresses copied into the buffer. - * If @p p_addrs is NULL, this parameter remains unchanged. - * @param[out] p_irks The buffer where to store IRKs. Pass NULL to retrieve - * only GAP addresses (in that case, @p p_addrs must not NULL). - * @param[in,out] p_irk_cnt In: The size of the @p p_irks buffer. - * May be NULL if and only if @p p_irks is NULL. - * Out: The number of IRKs copied into the buffer. - * If @p p_irks is NULL, this paramater remains unchanged. - * - * @retval NRF_SUCCESS If the whitelist was successfully retrieved. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be used for - * whitelisting (this error can occur only - * when using the S13x SoftDevice v2.x). - * @retval NRF_ERROR_NULL If a required parameter is NULL. - * @retval NRF_ERROR_NO_MEM If the provided buffers are too small. - * @retval NRF_ERROR_NOT_FOUND If the data for any of the cached whitelisted peers - * cannot be found. It might have been deleted. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_whitelist_get(ble_gap_addr_t * p_addrs, - uint32_t * p_addr_cnt, - ble_gap_irk_t * p_irks, - uint32_t * p_irk_cnt); - - -/**@brief Function for setting and clearing the device identities list. - * - * @param[in] p_peers The peers to add to the device identities list. Pass NULL to clear - * the device identities list. - * @param[in] peer_cnt The number of peers. Pass zero to clear the device identities list. - * - * @retval NRF_SUCCESS If the device identities list was successfully - * set or cleared. - * @retval NRF_ERROR_NOT_FOUND If a peer is invalid or its data could not - * be found in flash. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If a peer has an address that cannot be - * used for whitelisting. - * @retval BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE If the device identities list is in use and - * cannot be set. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_NOT_SUPPORTED If using a SoftDevice that does not support - * device identities, e.g. S130 v2.0. - */ -ret_code_t pm_device_identities_list_set(pm_peer_id_t const * p_peers, - uint32_t peer_cnt); - - -/**@brief Function for setting the local Bluetooth identity address. - * - * @details The local Bluetooth identity address is the address that identifies the device - * to other peers. The address type must be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. The identity address cannot be changed while roles are running. - * - * The SoftDevice sets a default address of type @ref BLE_GAP_ADDR_TYPE_RANDOM_STATIC when it is - * enabled. This default address is a random number that is populated during the IC manufacturing - * process. It remains unchanged for the lifetime of each IC, but the application can use this - * function to assign a different identity address. - * - * The identity address is distributed to the peer during bonding. Changing the identity address - * means bonded devices might not recognize us. - * - * - * @param[in] p_addr The GAP address to be set. - * - * @retval NRF_SUCCESS If the identity address was set successfully. - * @retval NRF_ERROR_NULL If @p p_addr is NULL. - * @retval NRF_ERROR_INVALID_ADDR If the @p p_addr pointer is invalid. - * @retval BLE_ERROR_GAP_INVALID_BLE_ADDR If the BLE address is invalid. - * @retval NRF_ERROR_BUSY If the SoftDevice was busy. Process SoftDevice events - * and retry. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized or if this function - * was called while advertising, scanning, or while connected. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_id_addr_set(ble_gap_addr_t const * p_addr); - - -/**@brief Function for retrieving the local Bluetooth identity address. - * - * This function always returns the identity address, irrespective of the privacy settings. - * This means that the address type will always be either @ref BLE_GAP_ADDR_TYPE_PUBLIC or @ref - * BLE_GAP_ADDR_TYPE_RANDOM_STATIC. - * - * @param[out] p_addr Pointer to the address structure to be filled in. - * - * @retval NRF_SUCCESS If the address was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_addr is NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_id_addr_get(ble_gap_addr_t * p_addr); - - -/**@brief Function for configuring privacy settings. - * - * The privacy settings cannot be configured while advertising, scanning, or while in a connection. - * - * @note The SoftDevice functions @ref sd_ble_gap_addr_set - * and @ref sd_ble_gap_privacy_set must not be called when using the Peer Manager. - * Use this function instead. - * - * @param[in] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If the privacy settings were configured successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params is NULL. - * @retval NRF_ERROR_BUSY If the operation could not be performed at this time. - * Process SoftDevice events and retry. - * @retval NRF_ERROR_INVALID_PARAM If the address type is invalid. - * @retval NRF_ERROR_INVALID_STATE If this function is called while BLE roles using - * privacy are enabled. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_privacy_set(pm_privacy_params_t const * p_privacy_params); - - -/**@brief Function for retrieving privacy settings. - * - * The privacy settings that are returned include the current IRK as well. - * - * @param[out] p_privacy_params Privacy settings. - * - * @retval NRF_SUCCESS If the privacy settings were retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_privacy_params or @p p_privacy_params->p_device_irk is - * NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_privacy_get(pm_privacy_params_t * p_privacy_params); - - -/**@brief Function for resolving a resolvable address with an identity resolution key (IRK). - * - * @param[in] p_addr A private random resolvable address. - * @param[in] p_irk An identity resolution key (IRK). - * - * @retval true The IRK used matched the one used to create the address. - * @retval false The IRK used did not match the one used to create the address, or an argument was - * NULL or invalid. - */ -bool pm_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk); - - -/**@brief Function for getting the connection handle of the connection with a bonded peer. - * - * @param[in] peer_id The peer ID of the bonded peer. - * @param[out] p_conn_handle Connection handle, or @ref BLE_ERROR_INVALID_CONN_HANDLE if the peer - * is not connected. - * - * @retval NRF_SUCCESS If the connection handle was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_conn_handle was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle); - - -/**@brief Function for retrieving the ID of a peer, given its connection handle. - * - * @param[in] conn_handle The connection handle of the peer. - * @param[out] p_peer_id The peer ID, or @ref PM_PEER_ID_INVALID if the peer is not bonded or - * @p conn_handle does not refer to a valid connection. - * - * @retval NRF_SUCCESS If the peer ID was retrieved successfully. - * @retval NRF_ERROR_NULL If @p p_peer_id was NULL. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id); - - -/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. - * - * @details This function can be used to loop through all used peer IDs. The order in which - * peer IDs are returned should be considered unpredictable. @ref PM_PEER_ID_INVALID - * is considered to be before the first and after the last used peer ID. - * - * @details To loop through all peer IDs exactly once, use the following constuct: - * @code{c} - * pm_peer_id_t current_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); - * while (current_peer_id != PM_PEER_ID_INVALID) - * { - * // Do something with current_peer_id. - * current_peer_id = pm_next_peer_id_get(current_peer_id) - * } - * @endcode - * - * @param[in] prev_peer_id The previous peer ID. - * - * @return The next peer ID. If @p prev_peer_id was @ref PM_PEER_ID_INVALID, the - * next peer ID is the first used peer ID. If @p prev_peer_id was the last - * used peer ID, the function returns @ref PM_PEER_ID_INVALID. - */ -pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id); - - -/**@brief Function for querying the number of valid peer IDs that are available. - * - * @details This function returns the number of peers for which there is data in persistent storage. - * - * @return The number of valid peer IDs. - */ -uint32_t pm_peer_count(void); - - - - -/**@anchor PM_PEER_DATA_FUNCTIONS - * @name Functions (Peer Data) - * Functions for manipulating peer data. - * @{ - */ - -/** - * @{ - */ - -/**@brief Function for retrieving stored data of a peer. - * - * @note The length of the provided buffer must be a multiple of 4. - * - * @param[in] peer_id Peer ID to get data for. - * @param[in] data_id Which type of data to read. - * @param[out] p_data Where to put the retrieved data. The documentation for - * @ref pm_peer_data_id_t specifies what data type each data ID is stored as. - * @param[inout] p_len In: The length in bytes of @p p_data. - * Out: The length in bytes of the read data, if the read was successful. - * - * @retval NRF_SUCCESS If the data was read successfully. - * @retval NRF_ERROR_INVALID_PARAM If the the data type or the peer ID was invalid or unallocated, - * or if the length in @p p_length was not a multiple of 4. - * @retval NRF_ERROR_NULL If a pointer parameter was NULL. - * @retval NRF_ERROR_NOT_FOUND If no stored data was found for this peer ID/data ID combination. - * @retval NRF_ERROR_DATA_SIZE If the provided buffer was not large enough. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_data_load(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void * p_data, - uint16_t * p_len); - -/**@brief Function for reading a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id, - pm_peer_data_bonding_t * p_data); - -/**@brief Function for reading a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id, - ble_gatt_db_srv_t * p_data, - uint16_t * p_len); - -/**@brief Function for reading a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). - * @details See @ref pm_peer_data_load for parameters and return values. */ -ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id, - void * p_data, - uint16_t * p_len); -/** @}*/ - - -/** - * @{ - */ - -/**@brief Function for setting or updating stored data of a peer. - * - * @note Writing the data to persistent storage happens asynchronously. Therefore, the buffer - * that contains the data must be kept alive until the operation has completed. - * - * @note The data written using this function might later be overwritten as a result of internal - * operations in the Peer Manager. A Peer Manager event is sent each time data is updated, - * regardless of whether the operation originated internally or from action by the user. - * - * @param[in] peer_id Peer ID to set data for. - * @param[in] data_id Which type of data to set. - * @param[in] p_data New value to set. The documentation for @ref pm_peer_data_id_t specifies - * what data type each data ID should be stored as. - * @param[in] len The length in bytes of @p p_data. - * @param[out] p_token A token that identifies this particular store operation. The token can be - * used to identify events that pertain to this operation. This parameter can - * be NULL. - * - * @retval NRF_SUCCESS If the data is scheduled to be written to persistent storage. - * @retval NRF_ERROR_NULL If @p p_data is NULL. - * @retval NRF_ERROR_NOT_FOUND If no peer was found for the peer ID. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_data_store(pm_peer_id_t peer_id, - pm_peer_data_id_t data_id, - void const * p_data, - uint16_t len, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id, - pm_peer_data_bonding_t const * p_data, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id, - ble_gatt_db_srv_t const * p_data, - uint16_t len, - pm_store_token_t * p_token); - -/**@brief Function for setting or updating a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION). - * @details See @ref pm_peer_data_store for parameters and return values. */ -ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id, - void const * p_data, - uint16_t len, - pm_store_token_t * p_token); -/** @}*/ - - -/** - * @{ - */ - -/**@brief Function for deleting a peer's stored pieces of data. - * - * @details This function deletes specific data that is stored for a peer. Note that bonding data - * cannot be cleared separately. - * - * To delete all data for a peer (including bonding data), use @ref pm_peer_delete. - * - * @note Clearing data in persistent storage happens asynchronously. - * - * @param[in] peer_id Peer ID to clear data for. - * @param[in] data_id Which data to clear. - * - * @retval NRF_SUCCESS If the clear procedure was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If @p data_id was PM_PEER_DATA_ID_BONDING or invalid, or - * @p peer_id was invalid. - * @retval NRF_ERROR_NOT_FOUND If there was no data to clear for this peer ID/data ID combination. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id); - - -/**@brief Function for manually adding a peer to the persistent storage. - * - * @details This function allocates a new peer ID and stores bonding data for the new peer. The - * bonding data is necessary to prevent ambiguity/inconsistency in peer data. - * - * @param[in] p_bonding_data The bonding data of the new peer (must contain a public/static - * address or a non-zero IRK). - * @param[out] p_new_peer_id Peer ID for the new peer, or an existing peer if a match was found. - * @param[out] p_token A token that identifies this particular store operation (storing the - * bonding data). The token can be used to identify events that pertain - * to this operation. This parameter can be NULL. - * - * @retval NRF_SUCCESS If the store operation for bonding data was initiated successfully. - * @retval NRF_ERROR_NULL If @p p_bonding_data or @p p_new_peer_id is NULL. - * @retval NRF_ERROR_STORAGE_FULL If there is no more space in persistent storage. - * @retval NRF_ERROR_NO_MEM If there are no more available peer IDs. - * @retval NRF_ERROR_BUSY If the underlying flash filesystem is busy with other flash - * operations. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id, - pm_peer_data_bonding_t * p_bonding_data, - pm_store_token_t * p_token); - - -/**@brief Function for freeing persistent storage for a peer. - * - * @details This function deletes every piece of data that is associated with the specified peer and - * frees the peer ID to be used for another peer. The deletion happens asynchronously, and - * the peer ID is not freed until the data is deleted. When the operation finishes, a @ref - * PM_EVT_PEER_DELETE_SUCCEEDED or @ref PM_EVT_PEER_DELETE_FAILED event is sent. - * - * @warning Use this function only when not connected to or connectable for the peer that is being - * deleted. If the peer is or becomes connected or data is manually written in flash during - * this procedure (until the success or failure event happens), the behavior is undefined. - * - * @param[in] peer_id Peer ID to be freed and have all associated data deleted. - * - * @retval NRF_SUCCESS If the operation was initiated successfully. - * @retval NRF_ERROR_INVALID_PARAM If the peer ID was not valid. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - */ -ret_code_t pm_peer_delete(pm_peer_id_t peer_id); - - -/**@brief Function for deleting all data stored for all peers. - * - * @details This function sends either a @ref PM_EVT_PEERS_DELETE_SUCCEEDED or a @ref - * PM_EVT_PEERS_DELETE_FAILED event. In addition, a @ref PM_EVT_PEER_DELETE_SUCCEEDED or - * @ref PM_EVT_PEER_DELETE_FAILED event is sent for each deleted peer. - * - * @note When there is no peer data in flash the @ref PM_EVT_PEER_DELETE_SUCCEEDED event is sent synchronously. - * - * @warning Use this function only when not connected or connectable. If a peer is or becomes - * connected or a @ref PM_PEER_DATA_FUNCTIONS function is used during this procedure (until - * the success or failure event happens), the behavior is undefined. - * - * @retval NRF_SUCCESS If the deletion process was initiated successfully. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peers_delete(void); -/** @}*/ - - -/** - * @{ - */ - - -/**@brief Function for finding the highest and lowest ranked peers. - * - * @details The rank is saved in persistent storage under the data ID @ref PM_PEER_DATA_ID_PEER_RANK. - * - * @details The interpretation of rank is up to the user, because the rank is only updated by - * calling @ref pm_peer_rank_highest or by manipulating the value using a @ref - * PM_PEER_DATA_FUNCTIONS function. - * - * @note Any argument that is NULL is ignored. - * - * @param[out] p_highest_ranked_peer The peer ID with the highest rank of all peers, for example, - * the most recently used peer. - * @param[out] p_highest_rank The highest rank. - * @param[out] p_lowest_ranked_peer The peer ID with the lowest rank of all peers, for example, - * the least recently used peer. - * @param[out] p_lowest_rank The lowest rank. - * - * @retval NRF_SUCCESS If the operation completed successfully. - * @retval NRF_ERROR_NOT_FOUND If no peers were found. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer, - uint32_t * p_highest_rank, - pm_peer_id_t * p_lowest_ranked_peer, - uint32_t * p_lowest_rank); - - -/**@brief Function for updating the rank of a peer to be highest among all stored peers. - * - * @details If this function returns @ref NRF_SUCCESS, either a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or a - * @ref PM_EVT_PEER_DATA_UPDATE_FAILED event is sent with a @ref - * PM_STORE_TOKEN_INVALID store token when the operation is complete. Until the operation - * is complete, this function returns @ref NRF_ERROR_BUSY. - * - * When the operation is complete, the peer is the highest ranked peer as reported by - * @ref pm_peer_ranks_get. - * - * @note The @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event can arrive before the function returns if the peer - * is already ranked highest. In this case, the @ref pm_peer_data_update_succeeded_evt_t::flash_changed flag - * in the event will be false. - * - * @param[in] peer_id The peer to rank highest. - * - * @retval NRF_SUCCESS If the peer's rank is, or will be updated to be highest. - * @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash - * operations, or if a previous call to this function has not - * completed. Try again after receiving a Peer Manager event. - * @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized. - * @retval NRF_ERROR_INTERNAL If an internal error occurred. - */ -ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id); - -/** @}*/ - -/** @} */ - -/** @} */ - - -#ifdef __cplusplus -} -#endif - -#endif // PEER_MANAGER_H__ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h deleted file mode 100644 index f3299d0a1e..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_internal.h +++ /dev/null @@ -1,207 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef PEER_MANAGER_INTERNAL_H__ -#define PEER_MANAGER_INTERNAL_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @file peer_manager_types.h - * - * @addtogroup peer_manager - * @brief File containing definitions used solely inside the Peer Manager's modules. - * @{ - */ - -ANON_UNIONS_ENABLE - -/**@brief One piece of data associated with a peer, together with its type. - * - * @note This type is deprecated. - */ -typedef struct -{ - uint16_t length_words; /**< @brief The length of the data in words. */ - pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ - union - { - pm_peer_data_bonding_t * p_bonding_data; /**< @brief The exchanged bond information in addition to metadata of the bonding. */ - uint32_t * p_peer_rank; /**< @brief A value locally assigned to this peer. Its interpretation is up to the user. The rank is not set automatically by the Peer Manager, but it is assigned by the user using either @ref pm_peer_rank_highest or a @ref PM_PEER_DATA_FUNCTIONS function. */ - bool * p_service_changed_pending; /**< @brief Whether a service changed indication should be sent to the peer. */ - pm_peer_data_local_gatt_db_t * p_local_gatt_db; /**< @brief Persistent information pertaining to a peer GATT client. */ - ble_gatt_db_srv_t * p_remote_gatt_db; /**< @brief Persistent information pertaining to a peer GATT server. */ - uint8_t * p_application_data; /**< @brief Arbitrary data to associate with the peer. This data can be freely used by the application. */ - void * p_all_data; /**< @brief Generic access pointer to the data. It is used only to handle the data without regard to type. */ - }; /**< @brief The data. */ -} pm_peer_data_t; - - -/**@brief Immutable version of @ref pm_peer_data_t. - * - * @note This type is deprecated. - */ -typedef struct -{ - uint16_t length_words; /**< @brief The length of the data in words. */ - pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */ - union - { - pm_peer_data_bonding_t const * p_bonding_data; /**< @brief Immutable @ref pm_peer_data_t::p_bonding_data. */ - uint32_t const * p_peer_rank; /**< @brief Immutable @ref pm_peer_data_t::p_peer_rank. */ - bool const * p_service_changed_pending; /**< @brief Immutable @ref pm_peer_data_t::p_service_changed_pending. */ - pm_peer_data_local_gatt_db_t const * p_local_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_local_gatt_db. */ - ble_gatt_db_srv_t const * p_remote_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_remote_gatt_db. */ - uint8_t const * p_application_data; /**< @brief Immutable @ref pm_peer_data_t::p_application_data. */ - void const * p_all_data; /**< @brief Immutable @ref pm_peer_data_t::p_all_data. */ - }; /**< @brief The data. */ -} pm_peer_data_const_t; - -ANON_UNIONS_DISABLE - - -/**@brief Version of @ref pm_peer_data_t that reflects the structure of peer data in flash. - * - * @note This type is deprecated. - */ -typedef pm_peer_data_const_t pm_peer_data_flash_t; - - -/**@brief Event handler for events from the @ref peer_manager module. - * - * @sa pm_register - * - * @param[in] p_event The event that has occurred. - */ -typedef void (*pm_evt_handler_internal_t)(pm_evt_t * p_event); - - -/**@brief Macro for calculating the flash size of bonding data. - * - * @return The number of words that the data takes in flash. - */ -#define PM_BONDING_DATA_N_WORDS() BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t)) - - -/**@brief Macro for calculating the flash size of service changed pending state. - * - * @return The number of words that the data takes in flash. - */ -#define PM_SC_STATE_N_WORDS() BYTES_TO_WORDS(sizeof(bool)) - - -/**@brief Macro for calculating the flash size of local GATT database data. - * - * @param[in] local_db_len The length, in bytes, of the database as reported by the SoftDevice. - * - * @return The number of words that the data takes in flash. - */ -#define PM_LOCAL_DB_N_WORDS(local_db_len) \ - BYTES_TO_WORDS((local_db_len) + PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - - -/**@brief Macro for calculating the length of a local GATT database attribute array. - * - * @param[in] n_words The number of words that the data takes in flash. - * - * @return The length of the database attribute array. - */ -#define PM_LOCAL_DB_LEN(n_words) (((n_words) * BYTES_PER_WORD) - PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - - -/**@brief Macro for calculating the flash size of remote GATT database data. - * - * @param[in] service_count The number of services in the service array. - * - * @return The number of words that the data takes in flash. - */ -#define PM_REMOTE_DB_N_WORDS(service_count) BYTES_TO_WORDS(sizeof(ble_gatt_db_srv_t) * (service_count)) - - -/**@brief Macro for calculating the flash size of remote GATT database data. - * - * @param[in] n_words The length in number of words. - * - * @return The number of words that the data takes in flash. - */ -#define PM_REMOTE_DB_N_SERVICES(n_words) (((n_words) * BYTES_PER_WORD) / sizeof(ble_gatt_db_srv_t)) - - -/**@brief Function for calculating the flash size of the usage index. - * - * @return The number of words that the data takes in flash. - */ -#define PM_USAGE_INDEX_N_WORDS() BYTES_TO_WORDS(sizeof(uint32_t)) - -/** @} - * @endcond - */ - - -#ifdef NRF_PM_DEBUG - - #define NRF_PM_DEBUG_CHECK(condition) \ - if (!(condition)) \ - { \ - __asm("bkpt #0"); \ - } - -#else - - // Prevent "variable set but never used" compiler warnings. - #define NRF_PM_DEBUG_CHECK(condition) (void)(condition) - -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_MANAGER_INTERNAL_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h deleted file mode 100644 index 8c699839fb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/peer_manager_types.h +++ /dev/null @@ -1,377 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -/** - * @file peer_manager_types.h - * - * @addtogroup peer_manager - * @{ - */ - -#ifndef PEER_MANAGER_TYPES_H__ -#define PEER_MANAGER_TYPES_H__ - -#include -#include -#include -#include "nrf.h" -#include "ble_gap.h" -#include "ble_hci.h" -#include "ble_gatt_db.h" -#include "app_util.h" -#include "app_util_platform.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/**@brief Handle to uniquely identify a peer for which we have persistently stored data. - */ -typedef uint16_t pm_peer_id_t; - -/**@brief Type that is used for write prepares (used to reserve space in flash). - */ -typedef uint32_t pm_prepare_token_t; - -/**@brief Type that is used to hold a reference to a stored item in flash. - */ -typedef uint32_t pm_store_token_t; - -/**@brief Errors from security procedures in Peer Manager. - * - * @details Possible values are defined in @ref PM_SEC_ERRORS and @ref BLE_GAP_SEC_STATUS. - */ -typedef uint16_t pm_sec_error_code_t; - - -//lint -emacro(516,PM_LOCAL_DB_LEN_OVERHEAD_BYTES) - -#define PM_PEER_ID_INVALID 0xFFFF /**< @brief Invalid value for @ref pm_peer_id_t. */ -#define PM_STORE_TOKEN_INVALID 0 /**< @brief Invalid value for store token. */ -#define PM_PEER_ID_N_AVAILABLE_IDS 256 /**< @brief The number of available peer IDs. */ -#define PM_LOCAL_DB_LEN_OVERHEAD_BYTES offsetof(pm_peer_data_local_gatt_db_t, data) /**< @brief The static-length part of the local GATT data struct. */ - - -#define PM_CONN_SEC_ERROR_BASE 0x1000 /**< @brief The base for Peer Manager defined errors. See @ref PM_SEC_ERRORS and @ref pm_sec_error_code_t. */ - - -/**@defgroup PM_SEC_ERRORS Peer Manager defined security errors - * - * @details The first 256 numbers in this range correspond to the status codes in - * @ref BLE_HCI_STATUS_CODES. - * @{ */ -#define PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING (PM_CONN_SEC_ERROR_BASE + 0x06) /**< @brief Encryption failed because the peripheral has lost the LTK for this bond. See also @ref BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING and Table 3.7 ("Pairing Failed Reason Codes") in the Bluetooth Core Specification 4.2, section 3.H.3.5.5 (@linkBLEcore). */ -#define PM_CONN_SEC_ERROR_MIC_FAILURE (PM_CONN_SEC_ERROR_BASE + 0x3D) /**< @brief Encryption ended with disconnection because of mismatching keys or a stray packet during a procedure. See the SoftDevice GAP Message Sequence Charts on encryption (@linkBLEMSCgap), the Bluetooth Core Specification 4.2, sections 6.B.5.1.3.1 and 3.H.3.5.5 (@linkBLEcore), and @ref BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE. */ -#define PM_CONN_SEC_ERROR_DISCONNECT (PM_CONN_SEC_ERROR_BASE + 0x100) /**< @brief Pairing or encryption did not finish before the link disconnected for an unrelated reason. */ -#define PM_CONN_SEC_ERROR_SMP_TIMEOUT (PM_CONN_SEC_ERROR_BASE + 0x101) /**< @brief Pairing/bonding could not start because an SMP time-out has already happened on this link. This means that no more pairing or bonding can happen on this link. To be able to pair or bond, the link must be disconnected and then reconnected. See Bluetooth Core Specification 4.2 section 3.H.3.4 (@linkBLEcore). */ - /** @} */ - - - -/**@defgroup PM_PEER_ID_VERSIONS All versions of Peer IDs. - * @brief The data ID for each iteration of the data formats in flash. - * @details Each time the format (in flash) of a piece of peer data changes, the data ID will also - * be updated. This list of defines is a record of each data ID that has ever existed, and - * code that caters to legacy formats can find the relevant IDs here. - * @{ */ -#define PM_PEER_DATA_ID_FIRST_VX 0 /**< @brief The smallest data ID. */ -#define PM_PEER_DATA_ID_BONDING_V1 0 /**< @brief The data ID of the first version of bonding data. */ -#define PM_PEER_DATA_ID_BONDING_V2 7 /**< @brief The data ID of the second version of bonding data. */ -#define PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1 1 /**< @brief The data ID of the first version of the service changed pending flag. */ -#define PM_PEER_DATA_ID_GATT_LOCAL_V1 2 /**< @brief The data ID of the first version of local GATT data. */ -#define PM_PEER_DATA_ID_GATT_LOCAL_V2 8 /**< @brief The data ID of the second version of local GATT data. */ -#define PM_PEER_DATA_ID_GATT_REMOTE_V1 3 /**< @brief The data ID of the first version of remote GATT data. */ -#define PM_PEER_DATA_ID_APPLICATION_V1 4 /**< @brief The data ID of the first version of application data. */ -#define PM_PEER_DATA_ID_GATT_REMOTE_V2 5 /**< @brief The data ID of the second version of remote GATT data. */ -#define PM_PEER_DATA_ID_PEER_RANK_V1 6 /**< @brief The data ID of the first version of the rank. */ -#define PM_PEER_DATA_ID_LAST_VX 9 /**< @brief The data ID after the last valid one. */ -#define PM_PEER_DATA_ID_INVALID_VX 0xFF /**< @brief A data ID guaranteed to be invalid. */ -/**@}*/ - - -/**@brief The different types of data associated with a peer. - */ -typedef enum -{ - PM_PEER_DATA_ID_FIRST = PM_PEER_DATA_ID_FIRST_VX, /**< @brief The smallest data ID. */ - PM_PEER_DATA_ID_BONDING = PM_PEER_DATA_ID_BONDING_V2, /**< @brief The data ID for bonding data. Type: @ref pm_peer_data_bonding_t. */ - PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1, /**< @brief The data ID for service changed state. Type: bool. */ - PM_PEER_DATA_ID_GATT_LOCAL = PM_PEER_DATA_ID_GATT_LOCAL_V2, /**< @brief The data ID for local GATT data (sys attributes). Type: @ref pm_peer_data_local_gatt_db_t. */ - PM_PEER_DATA_ID_GATT_REMOTE = PM_PEER_DATA_ID_GATT_REMOTE_V2, /**< @brief The data ID for remote GATT data. Type: uint8_t array. */ - PM_PEER_DATA_ID_PEER_RANK = PM_PEER_DATA_ID_PEER_RANK_V1, /**< @brief The data ID for peer rank. See @ref pm_peer_rank_highest. Type: uint32_t. */ - PM_PEER_DATA_ID_APPLICATION = PM_PEER_DATA_ID_APPLICATION_V1, /**< @brief The data ID for application data. Type: uint8_t array. */ - PM_PEER_DATA_ID_LAST = PM_PEER_DATA_ID_LAST_VX, /**< @brief One more than the highest data ID. */ - PM_PEER_DATA_ID_INVALID = PM_PEER_DATA_ID_INVALID_VX, /**< @brief A data ID guaranteed to be invalid. */ -} pm_peer_data_id_t; - - -/**@brief Different procedures that can lead to an encrypted link. - */ -typedef enum -{ - PM_LINK_SECURED_PROCEDURE_ENCRYPTION, /**< @brief Using an LTK that was shared during a previous bonding procedure to encrypt the link. */ - PM_LINK_SECURED_PROCEDURE_BONDING, /**< @brief A pairing procedure, followed by a bonding procedure. */ - PM_LINK_SECURED_PROCEDURE_PAIRING, /**< @brief A pairing procedure with no bonding. */ -} pm_conn_sec_procedure_t; - - -/**@brief Configuration of a security procedure. - */ -typedef struct -{ - bool allow_repairing; /** @brief Whether to allow the peer to pair if it wants to, but is already bonded. If this is false, the procedure is rejected, and no more events are sent. Default: false. */ -} pm_conn_sec_config_t; - - -/**@brief Data associated with a bond to a peer. - */ -typedef struct -{ - uint8_t own_role; /**< @brief The BLE role of the local device during bonding. See @ref BLE_GAP_ROLES. */ - ble_gap_id_key_t peer_ble_id; /**< @brief The peer's Bluetooth address and identity resolution key (IRK). */ - ble_gap_enc_key_t peer_ltk; /**< @brief The peer's long-term encryption key (LTK) and master ID. */ - ble_gap_enc_key_t own_ltk; /**< @brief Locally generated long-term encryption key (LTK) and master ID, distributed to the peer. */ -} pm_peer_data_bonding_t; - - -/**@brief Data on a local GATT database. - */ -typedef struct -{ - uint32_t flags; /**< @brief Flags that describe the database attributes. */ - uint16_t len; /**< @brief Size of the attribute array. */ - uint8_t data[1]; /**< @brief Array to hold the database attributes. */ -} pm_peer_data_local_gatt_db_t; - - -/**@brief Device Privacy. - * - * The privacy feature provides a way for the device to avoid being tracked over a period of - * time. The privacy feature, when enabled, hides the local device identity and replaces it - * with a private address that is automatically refreshed at a specified interval. - * - * If a device still wants to be recognized by other peers, it needs to share it's Identity - * Resolving Key (IRK). With this key, a device can generate a random private address that - * can only be recognized by peers in possession of that key, and devices can establish - * connections without revealing their real identities. - * - * @note If the device IRK is updated, the new IRK becomes the one to be distributed in all - * bonding procedures performed after @ref sd_ble_gap_privacy_set returns. - * The IRK distributed during bonding procedure is the device IRK that is active when @ref - * sd_ble_gap_sec_params_reply is called. - */ -#if (NRF_SD_BLE_API_VERSION < 3) - -typedef struct -{ - uint8_t privacy_mode; /**< Privacy mode, see @ref BLE_GAP_PRIVACY_MODES. Default is @ref BLE_GAP_PRIVACY_MODE_OFF. */ - uint8_t private_addr_type; /**< The private address type must be either @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE or @ref BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE. */ - uint16_t private_addr_cycle_s; /**< Private address cycle interval in seconds. Providing an address cycle value of 0 will use the default value defined by @ref BLE_GAP_DEFAULT_PRIVATE_ADDR_CYCLE_INTERVAL_S. */ - ble_gap_irk_t * p_device_irk; /**< When used as input, pointer to IRK structure that will be used as the default IRK. If NULL, the device default IRK will be used. - When used as output, pointer to IRK structure where the current default IRK will be written to. If NULL, this argument is ignored. - By default, the default IRK is used to generate random private resolvable addresses for the local device unless instructed otherwise. */ -} pm_privacy_params_t; - - -/**@defgroup BLE_GAP_PRIVACY_MODES Privacy modes - * @{ */ -#define BLE_GAP_PRIVACY_MODE_OFF 0x00 /**< Device will send and accept its identity address for its own address. */ -#define BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY 0x01 /**< Device will send and accept only private addresses for its own address. */ -/**@} */ - -#else - -typedef ble_gap_privacy_params_t pm_privacy_params_t; - -#endif - - -/**@brief Types of events that can come from the @ref peer_manager module. - */ -typedef enum -{ - PM_EVT_BONDED_PEER_CONNECTED, /**< @brief A connected peer has been identified as one with which we have a bond. When performing bonding with a peer for the first time, this event will not be sent until a new connection is established with the peer. When we are central, this event is always sent when the Peer Manager receives the @ref BLE_GAP_EVT_CONNECTED event. When we are peripheral, this event might in rare cases arrive later. */ - PM_EVT_CONN_SEC_START, /**< @brief A security procedure has started on a link, initiated either locally or remotely. The security procedure is using the last parameters provided via @ref pm_sec_params_set. This event is always followed by either a @ref PM_EVT_CONN_SEC_SUCCEEDED or a @ref PM_EVT_CONN_SEC_FAILED event. This is an informational event; no action is needed for the procedure to proceed. */ - PM_EVT_CONN_SEC_SUCCEEDED, /**< @brief A link has been encrypted, either as a result of a call to @ref pm_conn_secure or a result of an action by the peer. The event structure contains more information about the circumstances. This event might contain a peer ID with the value @ref PM_PEER_ID_INVALID, which means that the peer (central) used an address that could not be identified, but it used an encryption key (LTK) that is present in the database. */ - PM_EVT_CONN_SEC_FAILED, /**< @brief A pairing or encryption procedure has failed. In some cases, this means that security is not possible on this link (temporarily or permanently). How to handle this error depends on the application. */ - PM_EVT_CONN_SEC_CONFIG_REQ, /**< @brief The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref pm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */ - PM_EVT_CONN_SEC_PARAMS_REQ, /**< @brief Security parameters (@ref ble_gap_sec_params_t) are needed for an ongoing security procedure. Reply with @ref pm_conn_sec_params_reply before the event handler returns. If no reply is sent, the parameters given in @ref pm_sec_params_set are used. If a peripheral connection, the central's sec_params will be available in the event. */ - PM_EVT_STORAGE_FULL, /**< @brief There is no more room for peer data in flash storage. To solve this problem, delete data that is not needed anymore and run a garbage collection procedure in FDS. */ - PM_EVT_ERROR_UNEXPECTED, /**< @brief An unrecoverable error happened inside Peer Manager. An operation failed with the provided error. */ - PM_EVT_PEER_DATA_UPDATE_SUCCEEDED, /**< @brief A piece of peer data was stored, updated, or cleared in flash storage. This event is sent for all successful changes to peer data, also those initiated internally in Peer Manager. To identify an operation, compare the store token in the event with the store token received during the initiating function call. Events from internally initiated changes might have invalid store tokens. */ - PM_EVT_PEER_DATA_UPDATE_FAILED, /**< @brief A piece of peer data could not be stored, updated, or cleared in flash storage. This event is sent instead of @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED for the failed operation. */ - PM_EVT_PEER_DELETE_SUCCEEDED, /**< @brief A peer was cleared from flash storage, for example because a call to @ref pm_peer_delete succeeded. This event can also be sent as part of a call to @ref pm_peers_delete or internal cleanup. */ - PM_EVT_PEER_DELETE_FAILED, /**< @brief A peer could not be cleared from flash storage. This event is sent instead of @ref PM_EVT_PEER_DELETE_SUCCEEDED for the failed operation. */ - PM_EVT_PEERS_DELETE_SUCCEEDED, /**< @brief A call to @ref pm_peers_delete has completed successfully. Flash storage now contains no peer data. */ - PM_EVT_PEERS_DELETE_FAILED, /**< @brief A call to @ref pm_peers_delete has failed, which means that at least one of the peers could not be deleted. Other peers might have been deleted, or might still be queued to be deleted. No more @ref PM_EVT_PEERS_DELETE_SUCCEEDED or @ref PM_EVT_PEERS_DELETE_FAILED events are sent until the next time @ref pm_peers_delete is called. */ - PM_EVT_LOCAL_DB_CACHE_APPLIED, /**< @brief Local database values for a peer (taken from flash storage) have been provided to the SoftDevice. */ - PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED, /**< @brief Local database values for a peer (taken from flash storage) were rejected by the SoftDevice, which means that either the database has changed or the user has manually set the local database to an invalid value (using @ref pm_peer_data_store). */ - PM_EVT_SERVICE_CHANGED_IND_SENT, /**< @brief A service changed indication has been sent to a peer, as a result of a call to @ref pm_local_database_has_changed. This event will be followed by a @ref PM_EVT_SERVICE_CHANGED_IND_CONFIRMED event if the peer acknowledges the indication. */ - PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< @brief A service changed indication that was sent has been confirmed by a peer. The peer can now be considered aware that the local database has changed. */ - PM_EVT_SLAVE_SECURITY_REQ, /**< @brief The peer (peripheral) has requested link encryption, which has been enabled. */ - PM_EVT_FLASH_GARBAGE_COLLECTED, /**< @brief The flash has been garbage collected (By FDS), possibly freeing up space. */ -} pm_evt_id_t; - - -/**@brief Events parameters specific to the @ref PM_EVT_CONN_SEC_START event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that has started. */ -} pm_conn_sec_start_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that led to securing the link. */ - bool data_stored; /**< @brief Whether bonding data was successfully requested to be stored. This is false if: No bonding happened, or an internal error occurred when trying to store the data, or if the data was rejected via @ref pm_conn_sec_config_reply. */ -} pm_conn_secured_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. - */ -typedef struct -{ - pm_conn_sec_procedure_t procedure; /**< @brief The procedure that failed. */ - pm_sec_error_code_t error; /**< @brief An error code that describes the failure. */ - uint8_t error_src; /**< @brief The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */ -} pm_conn_secure_failed_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. - */ -typedef struct -{ - ble_gap_sec_params_t const * p_peer_params; /**< @brief Peer security parameters, if role is peripheral. Otherwise, this is NULL. */ - void const * p_context; /**< @brief This pointer must be provided in the reply if the reply function takes a p_context argument. */ -} pm_conn_sec_params_req_evt_t; - - -/**@brief Actions that can be performed to peer data in persistent storage. - */ -typedef enum -{ - PM_PEER_DATA_OP_UPDATE, /**< @brief Writing or overwriting the data. */ - PM_PEER_DATA_OP_DELETE, /**< @brief Removing the data. */ -} pm_peer_data_op_t; - - -/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. - */ -typedef struct -{ - pm_peer_data_id_t data_id; /**< @brief The type of the data that was changed. */ - pm_peer_data_op_t action; /**< @brief What happened to the data. */ - pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ - uint8_t flash_changed : 1; /**< @brief If this is false, no operation was done in flash, because the value was already what it should be. Please note that in certain scenarios, this flag will be true even if the new value is the same as the old. */ -} pm_peer_data_update_succeeded_evt_t; - - -/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. - */ -typedef struct -{ - pm_peer_data_id_t data_id; /**< @brief The type of the data that was supposed to be changed. */ - pm_peer_data_op_t action; /**< @brief The action that failed. */ - pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */ - ret_code_t error; /**< @brief An error code that describes the failure. */ -} pm_peer_data_update_failed_t; - - -/**@brief Standard parameters for failure events. - */ -typedef struct -{ - ret_code_t error; /**< @brief The error that occurred. */ -} pm_failure_evt_t; - - -/**@brief Events parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. - */ -typedef struct -{ - bool bond; /**< @brief Whether the peripheral requested bonding. */ - bool mitm; /**< @brief Whether the peripheral requested man-in-the-middle protection. */ -} pm_evt_slave_security_req_t; - - -/**@brief An event from the @ref peer_manager module. - * - * @details The structure contains both standard parameters and parameters that are specific to some events. - */ -typedef struct -{ - pm_evt_id_t evt_id; /**< @brief The type of the event. */ - uint16_t conn_handle; /**< @brief The connection that this event pertains to, or @ref BLE_CONN_HANDLE_INVALID. */ - pm_peer_id_t peer_id; /**< @brief The bonded peer that this event pertains to, or @ref PM_PEER_ID_INVALID. */ - union - { - pm_conn_sec_start_evt_t conn_sec_start; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_START event. */ - pm_conn_secured_evt_t conn_sec_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. */ - pm_conn_secure_failed_evt_t conn_sec_failed; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. */ - pm_conn_sec_params_req_evt_t conn_sec_params_req; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_PARAMS_REQ event. */ - pm_peer_data_update_succeeded_evt_t peer_data_update_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. */ - pm_peer_data_update_failed_t peer_data_update_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. */ - pm_failure_evt_t peer_delete_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */ - pm_failure_evt_t peers_delete_failed_evt; /**< @brief Parameters specific to the @ref PM_EVT_PEERS_DELETE_FAILED event. */ - pm_failure_evt_t error_unexpected; /**< @brief Parameters specific to the @ref PM_EVT_ERROR_UNEXPECTED event. */ - pm_evt_slave_security_req_t slave_security_req; /**< @brief Parameters specific to the @ref PM_EVT_SLAVE_SECURITY_REQ event. */ - } params; -} pm_evt_t; - - -/**@brief Event handler for events from the @ref peer_manager module. - * - * @sa pm_register - * - * @param[in] p_event The event that has occurred. - */ -typedef void (*pm_evt_handler_t)(pm_evt_t const * p_event); - -#ifdef __cplusplus -} -#endif - -#endif /* PEER_MANAGER_TYPES_H__ */ - -/** @} */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c deleted file mode 100644 index 83fdf77f11..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.c +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "pm_buffer.h" - -#include -#include -#include "nrf_error.h" -#include "pm_mutex.h" - - -#define BUFFER_IS_VALID(p_buffer) ((p_buffer != NULL) \ - && (p_buffer->p_memory != NULL) \ - && (p_buffer->p_mutex != NULL)) - - - -ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, - uint8_t * p_buffer_memory, - uint32_t buffer_memory_size, - uint8_t * p_mutex_memory, - uint32_t mutex_memory_size, - uint32_t n_blocks, - uint32_t block_size) -{ - if ( (p_buffer != NULL) - && (p_buffer_memory != NULL) - && (p_mutex_memory != NULL) - && (buffer_memory_size >= (n_blocks * block_size)) - && (mutex_memory_size >= MUTEX_STORAGE_SIZE(n_blocks)) - && (n_blocks != 0) - && (block_size != 0)) - { - p_buffer->p_memory = p_buffer_memory; - p_buffer->p_mutex = p_mutex_memory; - p_buffer->n_blocks = n_blocks; - p_buffer->block_size = block_size; - pm_mutex_init(p_buffer->p_mutex, n_blocks); - - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } -} - - -uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks) -{ - if (!BUFFER_IS_VALID(p_buffer)) - { - return ( PM_BUFFER_INVALID_ID ); - } - - uint8_t first_locked_mutex = PM_BUFFER_INVALID_ID; - - for (uint8_t i = 0; i < p_buffer->n_blocks; i++) - { - if (pm_mutex_lock(p_buffer->p_mutex, i)) - { - if (first_locked_mutex == PM_BUFFER_INVALID_ID) - { - first_locked_mutex = i; - } - if ((i - first_locked_mutex + 1) == n_blocks) - { - return first_locked_mutex; - } - } - else if (first_locked_mutex != PM_BUFFER_INVALID_ID) - { - for (uint8_t j = first_locked_mutex; j < i; j++) - { - pm_buffer_release(p_buffer, j); - } - first_locked_mutex = PM_BUFFER_INVALID_ID; - } - } - - return ( PM_BUFFER_INVALID_ID ); -} - - -uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id) -{ - if (!BUFFER_IS_VALID(p_buffer)) - { - return ( NULL ); - } - - if ( (id != PM_BUFFER_INVALID_ID) - && pm_mutex_lock_status_get(p_buffer->p_mutex, id) ) - { - return ( &p_buffer->p_memory[id * p_buffer->block_size] ); - } - else - { - return ( NULL ); - } -} - - -void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id) -{ - if ( BUFFER_IS_VALID(p_buffer) - && (id != PM_BUFFER_INVALID_ID) - && pm_mutex_lock_status_get(p_buffer->p_mutex, id)) - { - pm_mutex_unlock(p_buffer->p_mutex, id); - } -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h deleted file mode 100644 index 3697441fbf..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_buffer.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef BUFFER_H__ -#define BUFFER_H__ - -#include -#include "compiler_abstraction.h" -#include "sdk_errors.h" -#include "pm_mutex.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup pm_buffer Buffer - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides a simple buffer. - */ - - -#define PM_BUFFER_INVALID_ID 0xFF //!< Invalid buffer block ID. - - -/**@brief Convenience macro for declaring memory and initializing a buffer instance. - * - * @param[out] p_buffer The buffer instance to initialize. - * @param[in] n_blocks The desired number of blocks in the buffer. - * @param[in] block_size The desired block size of the buffer. - * @param[out] err_code The return code from @ref pm_buffer_init. - */ -#define PM_BUFFER_INIT(p_buffer, n_blocks, block_size, err_code) \ -do \ -{ \ - __ALIGN(4) static uint8_t buffer_memory[(n_blocks) * (block_size)]; \ - static uint8_t mutex_memory[MUTEX_STORAGE_SIZE(n_blocks)]; \ - err_code = pm_buffer_init((p_buffer), \ - buffer_memory, \ - (n_blocks) * (block_size), \ - mutex_memory, \ - MUTEX_STORAGE_SIZE(n_blocks), \ - (n_blocks), \ - (block_size)); \ -} while (0) - - -typedef struct -{ - uint8_t * p_memory; /**< The storage for all buffer entries. The size of the buffer must be n_blocks*block_size. */ - uint8_t * p_mutex; /**< A mutex group with one mutex for each buffer entry. */ - uint32_t n_blocks; /**< The number of allocatable blocks in the buffer. */ - uint32_t block_size; /**< The size of each block in the buffer. */ -} pm_buffer_t; - -/**@brief Function for initializing a buffer instance. - * - * @param[out] p_buffer The buffer instance to initialize. - * @param[in] p_buffer_memory The memory this buffer will use. - * @param[in] buffer_memory_size The size of p_buffer_memory. This must be at least - * n_blocks*block_size. - * @param[in] p_mutex_memory The memory for the mutexes. This must be at least - * @ref MUTEX_STORAGE_SIZE(n_blocks). - * @param[in] mutex_memory_size The size of p_mutex_memory. - * @param[in] n_blocks The number of blocks in the buffer. - * @param[in] block_size The size of each block. - * - * @retval NRF_SUCCESS Successfully initialized buffer instance. - * @retval NRF_ERROR_INVALID_PARAM A parameter was 0 or NULL or a size was too small. - */ -ret_code_t pm_buffer_init(pm_buffer_t * p_buffer, - uint8_t * p_buffer_memory, - uint32_t buffer_memory_size, - uint8_t * p_mutex_memory, - uint32_t mutex_memory_size, - uint32_t n_blocks, - uint32_t block_size); - - -/**@brief Function for acquiring a buffer block in a buffer. - * - * @param[in] p_buffer The buffer instance acquire from. - * @param[in] n_blocks The number of contiguous blocks to acquire. - * - * @return The id of the acquired block, if successful. - * @retval PM_BUFFER_INVALID_ID If unsuccessful. - */ -uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks); - - -/**@brief Function for getting a pointer to a specific buffer block. - * - * @param[in] p_buffer The buffer instance get from. - * @param[in] id The id of the buffer to get the pointer for. - * - * @return A pointer to the buffer for the specified id, if the id is valid. - * @retval NULL If the id is invalid. - */ -uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id); - - -/**@brief Function for releasing a buffer block. - * - * @param[in] p_buffer The buffer instance containing the block to release. - * @param[in] id The id of the block to release. - */ -void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id); - - - -#ifdef __cplusplus -} -#endif - -#endif // BUFFER_H__ - -/** - * @} - * @endcond - */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c deleted file mode 100644 index 10c26078b0..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.c +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "pm_mutex.h" - -#include -#include -#include "nrf_error.h" -#include "app_util_platform.h" - - - -/**@brief Locks the mutex defined by the mask. - * - * @param p_mutex pointer to the mutex storage. - * @param mutex_mask the mask identifying the mutex position. - * - * @retval true if the mutex could be locked. - * @retval false if the mutex was already locked. - */ -static bool lock_by_mask(uint8_t * p_mutex, uint8_t mutex_mask) -{ - bool success = false; - - if ( (*p_mutex & mutex_mask) == 0 ) - { - CRITICAL_REGION_ENTER(); - if ( (*p_mutex & mutex_mask) == 0 ) - { - *p_mutex |= mutex_mask; - - success = true; - } - CRITICAL_REGION_EXIT(); - } - - return ( success ); -} - - -void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size) -{ - if (p_mutex != NULL) - { - memset(&p_mutex[0], 0, MUTEX_STORAGE_SIZE(mutex_size)); - } -} - - -bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_id) -{ - if (p_mutex != NULL) - { - return ( lock_by_mask(&(p_mutex[mutex_id >> 3]), (1 << (mutex_id & 0x07))) ); - } - else - { - return false; - } -} - - -void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_id) -{ - uint8_t mutex_base = mutex_id >> 3; - uint8_t mutex_mask = (1 << (mutex_id & 0x07)); - - if ((p_mutex != NULL) - && (p_mutex[mutex_base] & mutex_mask)) - { - CRITICAL_REGION_ENTER(); - p_mutex[mutex_base] &= ~mutex_mask; - CRITICAL_REGION_EXIT(); - } -} - - -uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size) -{ - if (p_mutex != NULL) - { - for ( uint16_t i = 0; i < mutex_size; i++ ) - { - if ( lock_by_mask(&(p_mutex[i >> 3]), 1 << (i & 0x07)) ) - { - return ( i ); - } - } - } - - return ( mutex_size ); -} - - -bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_id) -{ - if (p_mutex != NULL) - { - return ( (p_mutex[mutex_id >> 3] & (1 << (mutex_id & 0x07))) ); - } - else - { - return true; - } -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h deleted file mode 100644 index 7031d73fcb..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/pm_mutex.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef MUTEX_H__ -#define MUTEX_H__ - - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @cond NO_DOXYGEN - * @defgroup pm_mutex Mutex - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. This module provides thread-safe mutexes. - */ - - -/**@brief Defines the storage size of a specified mutex group. - * - * @param number_of_mutexes the number of mutexes in the group. - */ -#define MUTEX_STORAGE_SIZE(number_of_mutexes) ((7 + (number_of_mutexes)) >> 3) - - -/**@brief Initializes a mutex group. - * - * @param[in] p_mutex Pointer to the mutex group. See @ref MUTEX_STORAGE_SIZE(). - * @param[in] mutex_size The size of the mutex group in number of mutexes. - */ -void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size); - - -/**@brief Locks the mutex specified by the bit id. - * - * @param[inout] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - * - * @retval true if it was possible to lock the mutex. - * @retval false otherwise. - */ -bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_bit_id); - - -/**@brief Locks the first unlocked mutex within the mutex group. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_size The size of the mutex group. - * - * @return The first unlocked mutex id in the group. - * @retval group-size if there was no unlocked mutex available. - */ -uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size); - - -/**@brief Unlocks the mutex specified by the bit id. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - */ -void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_bit_id); - - -/**@brief Gets the locking status of the specified mutex. - * - * @param[in, out] p_mutex Pointer to the mutex group. - * @param[in] mutex_bit_id The bit id of the mutex. - * - * @retval true if the mutex was locked. - * @retval false otherwise. - */ -bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_bit_id); - - - -#ifdef __cplusplus -} -#endif - -#endif // MUTEX_H__ - -/** @} - * @endcond - */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c deleted file mode 100644 index b36fea2aae..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.c +++ /dev/null @@ -1,1119 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "security_dispatcher.h" - -#include -#include "nrf_ble.h" -#include "ble_gap.h" -#include "ble_err.h" -#include "ble_conn_state.h" -#include "peer_manager_types.h" -#include "peer_database.h" -#include "id_manager.h" - -#ifndef PM_CENTRAL_ENABLED - #define PM_CENTRAL_ENABLED 1 -#endif - -// The number of registered event handlers. -#define SMD_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - -STATIC_ASSERT((NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0) || PM_CENTRAL_ENABLED, - "Peer Manager Central operation must be enabled when using central links."); - -// Security Dispacher event handlers in Security Manager and GATT Cache Manager. -extern void sm_smd_evt_handler(pm_evt_t * p_event); - -// Security Dispatcher events' handlers. -// The number of elements in this array is SMD_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - sm_smd_evt_handler -}; - -static bool m_module_initialized; - -static ble_conn_state_user_flag_id_t m_flag_sec_proc = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_pairing = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_bonding = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_sec_proc_new_peer = BLE_CONN_STATE_USER_FLAG_INVALID; -static ble_conn_state_user_flag_id_t m_flag_allow_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; - -static ble_gap_lesc_p256_pk_t m_peer_pk; - - -static __INLINE bool sec_procedure(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc); -} - -static __INLINE bool pairing(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_pairing); -} - -static __INLINE bool bonding(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_bonding); -} - -static __INLINE bool peer_created(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_sec_proc_new_peer); -} - -static __INLINE bool allow_repairing(uint16_t conn_handle) -{ - return ble_conn_state_user_flag_get(conn_handle, m_flag_allow_repairing); -} - - -/**@brief Function for sending an SMD event to all event handlers. - * - * @param[in] p_event The event to pass to all event handlers. - */ -static void evt_send(pm_evt_t * p_event) -{ - p_event->peer_id = im_peer_id_get_by_conn_handle(p_event->conn_handle); - - for (uint32_t i = 0; i < SMD_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for sending a PM_EVT_CONN_SEC_START event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] procedure The procedure that has started on the connection. - */ -static void sec_start_send(uint16_t conn_handle, - pm_conn_sec_procedure_t procedure) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_START, - .conn_handle = conn_handle, - .params = {.conn_sec_start = {.procedure = procedure}} - }; - evt_send(&evt); -} - - -/**@brief Function for sending a PM_EVT_ERROR_UNEXPECTED event. - * - * @param[in] conn_handle The connection handle the event pertains to. - * @param[in] err_code The unexpected error that occurred. - */ -static void send_unexpected_error(uint16_t conn_handle, ret_code_t err_code) -{ - pm_evt_t error_evt = - { - .evt_id = PM_EVT_ERROR_UNEXPECTED, - .conn_handle = conn_handle, - .params = - { - .error_unexpected = - { - .error = err_code, - } - } - }; - evt_send(&error_evt); -} - - -/**@brief Function for cleaning up after a failed security procedure. - * - * @param[in] conn_handle The handle of the connection the security procedure happens on. - * @param[in] procedure The procedure that failed. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static void conn_sec_failure(uint16_t conn_handle, - pm_conn_sec_procedure_t procedure, - pm_sec_error_code_t error, - uint8_t error_src) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_FAILED, - .conn_handle = conn_handle, - .params = - { - .conn_sec_failed = - { - .procedure = procedure, - .error = error, - .error_src = error_src, - } - } - }; - - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); - - evt_send(&evt); - return; -} - - -/**@brief Function for cleaning up after a failed pairing procedure. - * - * @param[in] conn_handle The handle of the connection the pairing procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The source of the error (local or remote). See @ref - * BLE_GAP_SEC_STATUS_SOURCES. - */ -static void pairing_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - ret_code_t err_code = NRF_SUCCESS; - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - pm_conn_sec_procedure_t procedure = bonding(conn_handle) ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - - if (peer_created(conn_handle)) - { - // The peer_id was created during the procedure, and should be freed, because no data is - // stored under it. - err_code = im_peer_free(peer_id); // Attempt to free allocated peer. - UNUSED_VARIABLE(err_code); - } - else if(peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND /* No buffer was allocated */)) - { - send_unexpected_error(conn_handle, err_code); - } - } - - conn_sec_failure(conn_handle, procedure, error, error_src); - - return; -} - - -/**@brief Function for cleaning up after a failed encryption procedure. - * - * @param[in] conn_handle The handle of the connection the encryption procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static __INLINE void encryption_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - conn_sec_failure(conn_handle, PM_LINK_SECURED_PROCEDURE_ENCRYPTION, error, error_src); - - return; -} - - -/**@brief Function for possibly cleaning up after a failed pairing or encryption procedure. - * - * @param[in] conn_handle The handle of the connection the pairing procedure happens on. - * @param[in] error The error the procedure failed with. - * @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES. - */ -static void link_secure_failure(uint16_t conn_handle, - pm_sec_error_code_t error, - uint8_t error_src) -{ - if (sec_procedure(conn_handle)) - { - if (pairing(conn_handle)) - { - pairing_failure(conn_handle, error, error_src); - } - else - { - encryption_failure(conn_handle, error, error_src); - } - } -} - - -/**@brief Function for administrative actions to be taken when a security process has started. - * - * @param[in] conn_handle The connection the security process was attempted on. - * @param[in] success Whether the procedure was started successfully. - * @param[in] procedure The procedure that was started. - */ -static void sec_proc_start(uint16_t conn_handle, - bool success, - pm_conn_sec_procedure_t procedure) -{ - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, success); - if (success) - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_sec_proc_pairing, - (procedure != PM_LINK_SECURED_PROCEDURE_ENCRYPTION)); - ble_conn_state_user_flag_set(conn_handle, - m_flag_sec_proc_bonding, - (procedure == PM_LINK_SECURED_PROCEDURE_BONDING)); - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, false); - sec_start_send(conn_handle, procedure); - } -} - - - -/**@brief Function for administrative actions to be taken during the course of a security process. - * - * @param[in] conn_handle The connection the security process was attempted on. - * @param[in] peer_id The peer ID given to the connected peer. - * @param[in] success Whether the process was started successfully. - * @param[in] new_peer_created Whether a new peer was created during the process attempt. - */ -static void sec_proc_housekeeping(uint16_t conn_handle, - pm_peer_id_t peer_id, - bool success, - bool new_peer_created) -{ - if (success) - { - if (new_peer_created) - { - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc_new_peer, true); - im_new_peer_id(conn_handle, peer_id); - } - } - else - { - if (new_peer_created) - { - ret_code_t err_code = im_peer_free(peer_id); // Attempt to free allocated peer. - UNUSED_VARIABLE(err_code); - } - } -} - - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_INFO_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_info_request_process(ble_gap_evt_t const * p_gap_evt) -{ - ret_code_t err_code; - ble_gap_enc_info_t const * p_enc_info = NULL; - pm_peer_data_flash_t peer_data; - pm_peer_id_t peer_id = im_peer_id_get_by_master_id( - &p_gap_evt->params.sec_info_request.master_id); - - if (peer_id == PM_PEER_ID_INVALID) - { - peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle); - } - else - { - // The peer might have been unrecognized until now (since connecting). E.g. if using a - // random non-resolvable advertising address. Report the discovered peer ID just in case. - im_new_peer_id(p_gap_evt->conn_handle, peer_id); - } - - sec_proc_start(p_gap_evt->conn_handle, true, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); - - if (peer_id != PM_PEER_ID_INVALID) - { - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); - - if (err_code == NRF_SUCCESS) - { - // There is stored bonding data for this peer. - ble_gap_enc_key_t const * p_existing_key = &peer_data.p_bonding_data->own_ltk; - - if ( p_existing_key->enc_info.lesc - || (im_master_ids_compare(&p_existing_key->master_id, - &p_gap_evt->params.sec_info_request.master_id))) - { - p_enc_info = &p_existing_key->enc_info; - } - } - } - - err_code = sd_ble_gap_sec_info_reply(p_gap_evt->conn_handle, p_enc_info, NULL, NULL); - - if (err_code != NRF_SUCCESS) - { - sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); - send_unexpected_error(p_gap_evt->conn_handle, err_code); - } - else if (p_enc_info == NULL) - { - sec_proc_housekeeping(p_gap_evt->conn_handle, peer_id, false, false); - encryption_failure(p_gap_evt->conn_handle, - PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, - BLE_GAP_SEC_STATUS_SOURCE_LOCAL); - } - - return; -} - - - -/**@brief Function for sending a CONFIG_REQ event. - * - * @param[in] conn_handle The connection the sec parameters are needed for. - */ -static void send_config_req(uint16_t conn_handle) -{ - pm_evt_t evt; - memset(&evt, 0, sizeof(evt)); - - evt.evt_id = PM_EVT_CONN_SEC_CONFIG_REQ; - evt.conn_handle = conn_handle; - - evt_send(&evt); -} - - -void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); - - ble_conn_state_user_flag_set(conn_handle, - m_flag_allow_repairing, - p_conn_sec_config->allow_repairing); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_DISCONNECT event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void disconnect_process(ble_gap_evt_t const * p_gap_evt) -{ - pm_sec_error_code_t error = (p_gap_evt->params.disconnected.reason - == BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE) - ? PM_CONN_SEC_ERROR_MIC_FAILURE : PM_CONN_SEC_ERROR_DISCONNECT; - - link_secure_failure(p_gap_evt->conn_handle, error, BLE_GAP_SEC_STATUS_SOURCE_LOCAL); -} - - -/**@brief Function for sending a PARAMS_REQ event. - * - * @param[in] conn_handle The connection the security parameters are needed for. - * @param[in] p_peer_params The security parameters from the peer. Can be NULL if the peer's parameters - * are not yet available. - */ -static void send_params_req(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_CONN_SEC_PARAMS_REQ, - .conn_handle = conn_handle, - .params = - { - .conn_sec_params_req = - { - .p_peer_params = p_peer_params - }, - }, - }; - - evt_send(&evt); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_params_request_process(ble_gap_evt_t const * p_gap_evt) -{ - if (ble_conn_state_role(p_gap_evt->conn_handle) == BLE_GAP_ROLE_PERIPH) - { - sec_proc_start(p_gap_evt->conn_handle, - true, - p_gap_evt->params.sec_params_request.peer_params.bond - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING); - } - - send_params_req(p_gap_evt->conn_handle, &p_gap_evt->params.sec_params_request.peer_params); - return; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when - * the auth_status is success. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_success_process(ble_gap_evt_t const * p_gap_evt) -{ - ret_code_t err_code = NRF_SUCCESS; - uint16_t conn_handle = p_gap_evt->conn_handle; - uint8_t role = ble_conn_state_role(conn_handle); - pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle); - pm_peer_id_t new_peer_id = peer_id; - pm_peer_data_t peer_data; - bool data_stored = false; - - ble_conn_state_user_flag_set(conn_handle, m_flag_sec_proc, false); - - if (role == BLE_GAP_ROLE_INVALID) - { - /* Unlikely, but maybe possible? */ - return; - } - - if (p_gap_evt->params.auth_status.bonded) - { - pm_peer_id_t duplicate_peer_id = PM_PEER_ID_INVALID; - data_stored = true; - - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); - if (err_code != NRF_SUCCESS) - { - send_unexpected_error(conn_handle, err_code); - data_stored = false; - } - else - { - duplicate_peer_id = im_find_duplicate_bonding_data(peer_data.p_bonding_data, - PM_PEER_ID_INVALID); - } - - if (duplicate_peer_id != PM_PEER_ID_INVALID) - { - // The peer has been identified as someone we have already bonded with. - new_peer_id = duplicate_peer_id; - im_new_peer_id(conn_handle, new_peer_id); - - // If the flag is true, the configuration has been requested before. - if (!allow_repairing(conn_handle)) - { - send_config_req(conn_handle); - if (!allow_repairing(conn_handle)) - { - data_stored = false; - } - } - } - - if (data_stored) - { - err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_BONDING, new_peer_id); - if (err_code != NRF_SUCCESS) - { - /* Unexpected */ - send_unexpected_error(conn_handle, err_code); - data_stored = false; - } - } - - if ((duplicate_peer_id != PM_PEER_ID_INVALID) && peer_created(conn_handle)) - { - // We already have a bond with the peer. Now that the data has been stored for the - // existing peer, the peer created for this bonding procedure can be freed. - ret_code_t err_code_free = im_peer_free(peer_id); - UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. - } - } - else if (peer_created(conn_handle)) - { - ret_code_t err_code_free = im_peer_free(peer_id); - UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored. - } - else - { - // No action. - } - - pm_evt_t pairing_success_evt; - - pairing_success_evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; - pairing_success_evt.conn_handle = conn_handle; - pairing_success_evt.params.conn_sec_succeeded.procedure = p_gap_evt->params.auth_status.bonded - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - pairing_success_evt.params.conn_sec_succeeded.data_stored = data_stored; - - evt_send(&pairing_success_evt); - - return; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when - * the auth_status is failure. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_failure_process(ble_gap_evt_t const * p_gap_evt) -{ - link_secure_failure(p_gap_evt->conn_handle, - p_gap_evt->params.auth_status.auth_status, - p_gap_evt->params.auth_status.error_src); -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void auth_status_process(ble_gap_evt_t const * p_gap_evt) -{ - switch (p_gap_evt->params.auth_status.auth_status) - { - case BLE_GAP_SEC_STATUS_SUCCESS: - auth_status_success_process(p_gap_evt); - break; - - default: - auth_status_failure_process(p_gap_evt); - break; - } -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_CONN_SEC_UPDATE event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void conn_sec_update_process(ble_gap_evt_t const * p_gap_evt) -{ - if (!pairing(p_gap_evt->conn_handle)) - { - // This is an encryption procedure (not pairing), so this event marks the end of the procedure. - - if (!ble_conn_state_encrypted(p_gap_evt->conn_handle)) - { - encryption_failure(p_gap_evt->conn_handle, - PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING, - BLE_GAP_SEC_STATUS_SOURCE_REMOTE); - } - else - { - ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_flag_sec_proc, false); - - pm_evt_t evt; - - evt.evt_id = PM_EVT_CONN_SEC_SUCCEEDED; - evt.conn_handle = p_gap_evt->conn_handle; - evt.params.conn_sec_succeeded.procedure = PM_LINK_SECURED_PROCEDURE_ENCRYPTION; - evt.params.conn_sec_succeeded.data_stored = false; - - evt_send(&evt); - } - } -} - - -/**@brief Funtion for initializing a BLE Connection State user flag. - * - * @param[out] flag_id The flag to initialize. - */ -static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) -{ - if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - *p_flag_id = ble_conn_state_user_flag_acquire(); - } -} - - -ret_code_t smd_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - flag_id_init(&m_flag_sec_proc); - flag_id_init(&m_flag_sec_proc_pairing); - flag_id_init(&m_flag_sec_proc_bonding); - flag_id_init(&m_flag_sec_proc_new_peer); - flag_id_init(&m_flag_allow_repairing); - - if ((m_flag_sec_proc == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_pairing == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_bonding == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_sec_proc_new_peer == BLE_CONN_STATE_USER_FLAG_INVALID) || - (m_flag_allow_repairing == BLE_CONN_STATE_USER_FLAG_INVALID)) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -/**@brief Function for putting retrieving a buffer and putting pointers into a @ref ble_gap_sec_keyset_t. - * - * @param[in] conn_handle The connection the security procedure is happening on. - * @param[in] peer_id The peer the security procedure is happening with. - * @param[in] role Our role in the connection. - * @param[in] p_public_key Pointer to a buffer holding the public key, or NULL. - * @param[out] p_sec_keyset Pointer to the keyset to be filled. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_STORAGE_FULL Not enough room in persistent storage. - * @retval NRF_ERROR_BUSY Could not process request at this time. Reattempt later. - * @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated. - * @retval NRF_ERROR_INTERNAL Fatal error. - */ -static ret_code_t sec_keyset_fill(uint16_t conn_handle, - pm_peer_id_t peer_id, - uint8_t role, - ble_gap_lesc_p256_pk_t * p_public_key, - ble_gap_sec_keyset_t * p_sec_keyset) -{ - ret_code_t err_code; - pm_peer_data_t peer_data; - - if (p_sec_keyset == NULL) - { - return NRF_ERROR_INTERNAL; - } - - // Acquire a memory buffer to receive bonding data into. - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data); - - if (err_code == NRF_ERROR_BUSY) - { - // No action. - } - else if (err_code != NRF_SUCCESS) - { - err_code = NRF_ERROR_INTERNAL; - } - else /* if (err_code == NRF_SUCCESS) */ - { - memset(peer_data.p_bonding_data, 0, sizeof(pm_peer_data_bonding_t)); - - peer_data.p_bonding_data->own_role = role; - - p_sec_keyset->keys_own.p_enc_key = &peer_data.p_bonding_data->own_ltk; - p_sec_keyset->keys_own.p_pk = p_public_key; - p_sec_keyset->keys_peer.p_enc_key = &peer_data.p_bonding_data->peer_ltk; - p_sec_keyset->keys_peer.p_id_key = &peer_data.p_bonding_data->peer_ble_id; - p_sec_keyset->keys_peer.p_pk = &m_peer_pk; - - // Retrieve the address the peer used during connection establishment. - // This address will be overwritten if ID is shared. Should not fail. - err_code = im_ble_addr_get(conn_handle, &peer_data.p_bonding_data->peer_ble_id.id_addr_info); - if (err_code != NRF_SUCCESS) - { - return NRF_ERROR_INTERNAL; - } - - // Buffer is OK, reserve room in flash for the data. - err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); - if (err_code == NRF_ERROR_NOT_FOUND) - { - return NRF_ERROR_INTERNAL; - } - } - - return err_code; -} - - -ret_code_t smd_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - ble_gap_lesc_p256_pk_t * p_public_key) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t role = ble_conn_state_role(conn_handle); - pm_peer_id_t peer_id = PM_PEER_ID_INVALID; - ret_code_t err_code = NRF_SUCCESS; - uint8_t sec_status = BLE_GAP_SEC_STATUS_SUCCESS; - bool new_peer_created = peer_created(conn_handle); - ble_gap_sec_keyset_t sec_keyset; - - memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t)); - if (role == BLE_GAP_ROLE_PERIPH) - { - // Set the default value for allowing repairing at the start of the sec proc. (for peripheral) - ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, false); - } - - if (role == BLE_GAP_ROLE_INVALID) - { - return BLE_ERROR_INVALID_CONN_HANDLE; - } - - if (p_sec_params == NULL) - { - // NULL params means reject pairing. - sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; - } - else if (!p_sec_params->bond) - { - // Pairing, no bonding. - - sec_keyset.keys_own.p_pk = p_public_key; - sec_keyset.keys_peer.p_pk = &m_peer_pk; - } - else - { - // Bonding is to be performed, prepare to receive bonding data. - - peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - if (peer_id == PM_PEER_ID_INVALID) - { - // Peer is unknown to us, allocate a new peer ID for it. - peer_id = pdb_peer_allocate(); - if (peer_id != PM_PEER_ID_INVALID) - { - new_peer_created = true; - } - else - { - err_code = NRF_ERROR_INTERNAL; - } - } - else if (role == BLE_GAP_ROLE_PERIPH && !allow_repairing(conn_handle)) - { - // Bond already exists. Reject the pairing request if the user doesn't intervene. - // send_config_req(conn_handle, peer_id); - send_config_req(conn_handle); - if (!allow_repairing(conn_handle)) - { - // Reject pairing. - sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP; - } - } - - if ((sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP) && (err_code == NRF_SUCCESS)) - { - err_code = sec_keyset_fill(conn_handle, peer_id, role, p_public_key, &sec_keyset); - } - } - - if (err_code == NRF_SUCCESS) - { - // Everything OK, reply to SoftDevice. If an error happened, the user is given an - // opportunity to change the parameters and retry the call. - if (role == BLE_GAP_ROLE_PERIPH) - { - err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_sec_params, &sec_keyset); - } - else - { - err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, NULL, &sec_keyset); - } - } - - sec_proc_housekeeping(conn_handle, - peer_id, - (err_code == NRF_SUCCESS) && (sec_status == BLE_GAP_SEC_STATUS_SUCCESS), - new_peer_created); - - return err_code; -} - - -#if PM_CENTRAL_ENABLED -/**@brief Function for initiating encryption as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central_encryption(uint16_t conn_handle, - pm_peer_id_t peer_id) -{ - pm_peer_data_flash_t peer_data; - ret_code_t err_code; - ble_gap_enc_key_t const * p_existing_key = NULL; - bool lesc = false; - - err_code = pdb_peer_data_ptr_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data); - - if (err_code == NRF_SUCCESS) - { - // Use peer's key since they are peripheral. - p_existing_key = &(peer_data.p_bonding_data->peer_ltk); - - lesc = peer_data.p_bonding_data->own_ltk.enc_info.lesc; - if (lesc) // LESC was used during bonding. - { - // For LESC, always use own key. - p_existing_key = &(peer_data.p_bonding_data->own_ltk); - } - } - - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) - { - if (err_code != NRF_ERROR_BUSY) - { - // Unexpected error code. - err_code = NRF_ERROR_INTERNAL; - } - } - else if (p_existing_key == NULL) /* There is no bonding data stored. This means that a bonding - procedure is in ongoing, or that the records in flash are - in a bad state. */ - { - err_code = NRF_ERROR_BUSY; - } - else if (!lesc && !im_master_id_is_valid(&(p_existing_key->master_id))) /* There is no valid LTK stored. */ - { - // No LTK to encrypt with. - err_code = NRF_ERROR_INVALID_DATA; - } - else - { - // Encrypt with existing LTK. - err_code = sd_ble_gap_encrypt(conn_handle, - &(p_existing_key->master_id), - &(p_existing_key->enc_info)); - } - - sec_proc_start(conn_handle, err_code == NRF_SUCCESS, PM_LINK_SECURED_PROCEDURE_ENCRYPTION); - sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), false); - - return err_code; -} - - -/**@brief Function for intiating pairing as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central_pairing(uint16_t conn_handle, - pm_peer_id_t peer_id, - ble_gap_sec_params_t * p_sec_params) -{ - pm_conn_sec_procedure_t procedure = PM_LINK_SECURED_PROCEDURE_PAIRING; - bool new_peer_created = false; - ret_code_t err_code = NRF_SUCCESS; - pm_peer_data_t dummy_peer_data; - - if (p_sec_params == NULL) - { - err_code = sd_ble_gap_authenticate(conn_handle, NULL); - } - else - { - if (p_sec_params->bond) - { - procedure = PM_LINK_SECURED_PROCEDURE_BONDING; - - if (peer_id == PM_PEER_ID_INVALID) - { - // New peer is required. - peer_id = pdb_peer_allocate(); - new_peer_created = true; - } - - if (peer_id == PM_PEER_ID_INVALID) - { - err_code = NRF_ERROR_INTERNAL; - } - else - { - err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &dummy_peer_data); - if (err_code == NRF_SUCCESS) - { - err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING); - } - } - } - - if (err_code == NRF_SUCCESS) - { - err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); - } - - if (err_code != NRF_SUCCESS) - { - ret_code_t err_code_free = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING); - if ((err_code_free != NRF_SUCCESS) && (err_code_free != NRF_ERROR_NOT_FOUND)) - { - err_code = NRF_ERROR_INTERNAL; - } - } - } - - if (err_code == NRF_ERROR_NO_MEM) - { - // sd_ble_gap_authenticate() returned NRF_ERROR_NO_MEM. Too many other sec procedures running. - err_code = NRF_ERROR_BUSY; - } - - sec_proc_start(conn_handle, err_code == NRF_SUCCESS, procedure); - sec_proc_housekeeping(conn_handle, peer_id, (err_code == NRF_SUCCESS), new_peer_created); - - return err_code; -} - - - -/**@brief Function for intiating security as a central. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_central(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing) -{ - ret_code_t err_code; - pm_peer_id_t peer_id; - - if (p_sec_params == NULL) - { - return sd_ble_gap_authenticate(conn_handle, NULL); - } - - // Set the default value for allowing repairing at the start of the sec proc. (for central) - ble_conn_state_user_flag_set(conn_handle, m_flag_allow_repairing, force_repairing); - - peer_id = im_peer_id_get_by_conn_handle(conn_handle); - - if ((peer_id != PM_PEER_ID_INVALID) && !force_repairing) - { - // There is already data in flash for this peer, and repairing has not been requested, so - // link will be encrypted with the existing keys. - err_code = link_secure_central_encryption(conn_handle, peer_id); - } - else - { - // There are no existing keys, or repairing has been explicitly requested, so pairing - // (possibly including bonding) will be performed to encrypt the link. - err_code = link_secure_central_pairing(conn_handle, peer_id, p_sec_params); - } - - return err_code; -} - - -/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_REQUEST event from the SoftDevice. - * - * @param[in] p_gap_evt The event from the SoftDevice. - */ -static void sec_request_process(ble_gap_evt_t const * p_gap_evt) -{ - pm_evt_t evt = - { - .evt_id = PM_EVT_SLAVE_SECURITY_REQ, - .conn_handle = p_gap_evt->conn_handle, - .params = - { - .slave_security_req = - { - .bond = p_gap_evt->params.sec_request.bond, - .mitm = p_gap_evt->params.sec_request.mitm, - } - } - }; - evt_send(&evt); - return; -} -#endif // PM_CENTRAL_ENABLED - - -/**@brief Function for asking the central to secure the link. See @ref smd_link_secure for more info. - */ -static ret_code_t link_secure_peripheral(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params) -{ - ret_code_t err_code = NRF_SUCCESS; - - if (p_sec_params != NULL) - { - err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params); - } - - return err_code; -} - - -ret_code_t smd_link_secure(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - uint8_t role = ble_conn_state_role(conn_handle); - - switch (role) - { -#if PM_CENTRAL_ENABLED - case BLE_GAP_ROLE_CENTRAL: - return link_secure_central(conn_handle, p_sec_params, force_repairing); -#endif - - case BLE_GAP_ROLE_PERIPH: - return link_secure_peripheral(conn_handle, p_sec_params); - - default: - return BLE_ERROR_INVALID_CONN_HANDLE; - } -} - - -void smd_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - switch (p_ble_evt->header.evt_id) - { - case BLE_GAP_EVT_DISCONNECTED: - disconnect_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - sec_params_request_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_SEC_INFO_REQUEST: - sec_info_request_process(&(p_ble_evt->evt.gap_evt)); - break; - -#if PM_CENTRAL_ENABLED - case BLE_GAP_EVT_SEC_REQUEST: - sec_request_process(&(p_ble_evt->evt.gap_evt)); - break; -#endif - - case BLE_GAP_EVT_AUTH_STATUS: - auth_status_process(&(p_ble_evt->evt.gap_evt)); - break; - - case BLE_GAP_EVT_CONN_SEC_UPDATE: - conn_sec_update_process(&(p_ble_evt->evt.gap_evt)); - break; - }; -} -#endif //NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h deleted file mode 100644 index b985fe25d3..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_dispatcher.h +++ /dev/null @@ -1,164 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef SECURITY_DISPATCHER_H__ -#define SECURITY_DISPATCHER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup security_dispatcher Security Dispatcher - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and - * encryption, including flash storage of shared data. - * - */ - - -/**@brief Function for initializing the Security Dispatcher module. - * - * @retval NRF_SUCCESS Initialization was successful. - * @retval NRF_ERROR_INTERNAL An unexpected fatal error occurred. - */ -ret_code_t smd_init(void); - - -/**@brief Function for dispatching SoftDevice events to the Security Dispatcher module. - * - * @param[in] ble_evt The SoftDevice event. - */ -void smd_ble_evt_handler(ble_evt_t const * ble_evt); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void smd_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing pairing and bonding parameters to use for the current pairing - * procedure on a connection. - * - * @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref - * BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_STORAGE_FULL, this function can be called - * again after corrective action. - * - * @note To reject a request, call this function with NULL p_sec_params. - * - * @param[in] conn_handle The connection handle of the connection the pairing is happening on. - * @param[in] p_sec_params The security parameters to use for this link. - * @param[in] p_public_key A pointer to the public key to use if using LESC, or NULL. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_INVALID_STATE No parameters have been requested on that conn_handle, or - * the link is disconnecting. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next - * FDS garbage collection procedure. - * @retval NRF_ERROR_BUSY No write buffer. Reattempt later. - * @retval NRF_ERROR_INTERNAL A fatal error occurred. - */ -ret_code_t smd_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - ble_gap_lesc_p256_pk_t * p_public_key); - - -/**@brief Function for initiating security on the link, with the specified parameters. - * - * @note If the connection is a peripheral connection, this will send a security request to the - * master, but the master is not obligated to initiate pairing or encryption in response. - * @note If the connection is a central connection and a key is available, the parameters will be - * used to determine whether to re-pair or to encrypt using the existing key. If no key is - * available, pairing will be started. - * - * @param[in] conn_handle Handle of the connection to initiate pairing on. - * @param[in] p_sec_params The security parameters to use for this link. As a central, this can - * be NULL to reject a slave security request. - * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether - * an encryption key already exists. This argument is only relevant for - * the central role. Recommended value: false - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_NULL p_sec_params was NULL (peripheral only). - * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, - * or the link is disconnecting. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle). - * @retval NRF_ERROR_BUSY Unable to initiate procedure at this time. - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_STORAGE_FULL No more room in flash. Fix and reattempt after the next - * FDS garbage collection procedure. - * @retval NRF_ERROR_INTERNAL No more available peer IDs. - */ -ret_code_t smd_link_secure(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - bool force_repairing); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* SECURITY_DISPATCHER_H__ */ diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c deleted file mode 100644 index c2c8ad7d1d..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.c +++ /dev/null @@ -1,695 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#include "sdk_common.h" -#if NRF_MODULE_ENABLED(PEER_MANAGER) -#include "security_manager.h" - -#include -#include "ble_err.h" -#include "security_dispatcher.h" -#include "peer_database.h" -#include "ble_conn_state.h" -#include "id_manager.h" - - -// The number of registered event handlers. -#define SM_EVENT_HANDLERS_CNT (sizeof(m_evt_handlers) / sizeof(m_evt_handlers[0])) - - -// Security Manager event handler in Peer Manager. -extern void pm_sm_evt_handler(pm_evt_t * p_sm_evt); - -// Security Manager events' handlers. -// The number of elements in this array is SM_EVENT_HANDLERS_CNT. -static pm_evt_handler_internal_t const m_evt_handlers[] = -{ - pm_sm_evt_handler -}; - - -// The context type that is used in PM_EVT_CONN_SEC_PARAMS_REQ events and in calls to sm_sec_params_reply(). -typedef struct -{ - ble_gap_sec_params_t * p_sec_params; //!< The security parameters to use in the call to the security_dispatcher - ble_gap_sec_params_t sec_params_mem; //!< The buffer for holding the security parameters. - bool params_reply_called; //!< Whether @ref sm_sec_params_reply has been called for this context instance. -} sec_params_reply_context_t; - -static bool m_module_initialized; //!< Whether the Security Manager module has been initialized. - -static ble_gap_sec_params_t m_sec_params; //!< The buffer for the default security parameters set by @ref sm_sec_params_set. -static ble_gap_sec_params_t * mp_sec_params = NULL; //!< The default security parameters set by @ref sm_sec_params_set. -static bool m_sec_params_set = false; //!< Whether @ref sm_sec_params_set has been called. - -static ble_gap_lesc_p256_pk_t * m_p_public_key; //!< Pointer, provided by the user, to the public key to use for LESC procedures. - -static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_BUSY. -static ble_conn_state_user_flag_id_t m_flag_link_secure_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_link_secure because it returned @ref NRF_ERROR_STORAGE_FULL. -static ble_conn_state_user_flag_id_t m_flag_link_secure_force_repairing = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with true for the force_repairing parameter. -static ble_conn_state_user_flag_id_t m_flag_link_secure_null_params = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a pending call to @ref sm_link_secure should be called with NULL security parameters. -static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_BUSY. -static ble_conn_state_user_flag_id_t m_flag_params_reply_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID; //!< User flag indicating whether a connection has a pending call to @ref sm_sec_params_reply because it returned @ref NRF_ERROR_STORAGE_FULL. - - -/**@brief Function for sending an SM event to all registered event handlers. - * - * @param[in] p_event The event to send. - */ -static void evt_send(pm_evt_t * p_event) -{ - for (uint32_t i = 0; i < SM_EVENT_HANDLERS_CNT; i++) - { - m_evt_handlers[i](p_event); - } -} - - -/**@brief Function for setting or clearing user flags based on error codes returned from @ref - * smd_link_secure or @ref smd_params_reply. - * - * @param[in] conn_handle The connection the call pertained to. - * @param[in] err_code The error code returned from @ref smd_link_secure or - * @ref smd_params_reply. - * @param[in] params_reply Whether the call was to @ref smd_params_reply. - */ -static void flags_set_from_err_code(uint16_t conn_handle, ret_code_t err_code, bool params_reply) -{ - bool flag_value_flash_full = false; - bool flag_value_busy = false; - - if ((err_code == NRF_ERROR_STORAGE_FULL)) - { - flag_value_busy = false; - flag_value_flash_full = true; - } - else if (err_code == NRF_ERROR_BUSY) - { - flag_value_busy = true; - flag_value_flash_full = false; - } - else - { - flag_value_busy = false; - flag_value_flash_full = false; - } - - if (params_reply) - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_params_reply_pending_flash_full, - flag_value_flash_full); - ble_conn_state_user_flag_set(conn_handle, - m_flag_params_reply_pending_busy, - flag_value_busy); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_flash_full, - false); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_busy, - false); - } - else - { - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_flash_full, - flag_value_flash_full); - ble_conn_state_user_flag_set(conn_handle, - m_flag_link_secure_pending_busy, - flag_value_busy); - } -} - - -/**@brief Function for sending an event based on error codes returned from @ref smd_link_secure or - * @ref smd_params_reply. - * - * @param[in] conn_handle The connection the event pertains to. - * @param[in] err_code The error code returned from @ref smd_link_secure or - * @ref smd_params_reply. - * @param[in] p_sec_params The security parameters attempted to pass in the call to - * @ref smd_link_secure or @ref smd_params_reply. - */ -static void events_send_from_err_code(uint16_t conn_handle, - ret_code_t err_code, - ble_gap_sec_params_t * p_sec_params) -{ - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY) && (err_code != NRF_ERROR_INVALID_STATE)) - { - pm_evt_t evt = - { - .conn_handle = conn_handle, - .peer_id = im_peer_id_get_by_conn_handle(conn_handle), - }; - if (err_code == NRF_ERROR_TIMEOUT) - { - evt.evt_id = PM_EVT_CONN_SEC_FAILED; - evt.params.conn_sec_failed.procedure = ((p_sec_params != NULL) && p_sec_params->bond) - ? PM_LINK_SECURED_PROCEDURE_BONDING - : PM_LINK_SECURED_PROCEDURE_PAIRING; - evt.params.conn_sec_failed.error_src = BLE_GAP_SEC_STATUS_SOURCE_LOCAL; - evt.params.conn_sec_failed.error = PM_CONN_SEC_ERROR_SMP_TIMEOUT; - } - else if (err_code == NRF_ERROR_STORAGE_FULL) - { - evt.evt_id = PM_EVT_STORAGE_FULL; - } - else - { - evt.evt_id = PM_EVT_ERROR_UNEXPECTED; - evt.params.error_unexpected.error = err_code; - } - evt_send(&evt); - } -} - - -/**@brief Function for sending an PM_EVT_CONN_SEC_PARAMS_REQ event. - * - * @param[in] conn_handle The connection the event pertains to. - * @param[in] p_peer_params The peer's security parameters to include in the event. Can be NULL. - * @param[in] p_context Pointer to a context that the user must include in the call to @ref - * sm_sec_params_reply(). - */ -static void params_req_send(uint16_t conn_handle, - ble_gap_sec_params_t const * p_peer_params, - sec_params_reply_context_t * p_context) -{ - pm_evt_t evt; - evt.evt_id = PM_EVT_CONN_SEC_PARAMS_REQ; - evt.conn_handle = conn_handle; - evt.peer_id = im_peer_id_get_by_conn_handle(conn_handle); - evt.params.conn_sec_params_req.p_peer_params = p_peer_params; - evt.params.conn_sec_params_req.p_context = p_context; - - evt_send(&evt); -} - - -/**@brief Function for creating a new @ref sec_params_reply_context_t with the correct initial values. - * - * @return The new context. - */ -static sec_params_reply_context_t new_context_get(void) -{ - sec_params_reply_context_t new_context = - { - .p_sec_params = mp_sec_params, - .params_reply_called = false - }; - return new_context; -} - - -/**@brief Internal function corresponding to @ref sm_link_secure. - * - * @param[in] conn_handle The connection to secure. - * @param[in] null_params Whether to pass NULL security parameters to the security_dispatcher. - * @param[in] force_repairing Whether to force rebonding if peer exists. - * @param[in] send_events Whether to send events based on the result of @ref smd_link_secure. - * - * @return Same return codes as @ref sm_link_secure. - */ -static ret_code_t link_secure(uint16_t conn_handle, - bool null_params, - bool force_repairing, - bool send_events) -{ - ret_code_t err_code; - ret_code_t return_err_code; - ble_gap_sec_params_t * p_sec_params; - - if (null_params) - { - p_sec_params = NULL; - } - else - { - sec_params_reply_context_t context = new_context_get(); - params_req_send(conn_handle, NULL, &context); - p_sec_params = context.p_sec_params; - - if (!m_sec_params_set && !context.params_reply_called) - { - // Security parameters have not been set. - return NRF_ERROR_NOT_FOUND; - } - } - - - err_code = smd_link_secure(conn_handle, p_sec_params, force_repairing); - - flags_set_from_err_code(conn_handle, err_code, false); - - switch (err_code) - { - case NRF_ERROR_BUSY: - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); - return_err_code = NRF_SUCCESS; - break; - case NRF_ERROR_STORAGE_FULL: - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_null_params, null_params); - ble_conn_state_user_flag_set(conn_handle, m_flag_link_secure_force_repairing, force_repairing); - /* fallthrough */ - case NRF_SUCCESS: - case NRF_ERROR_TIMEOUT: - case BLE_ERROR_INVALID_CONN_HANDLE: - case NRF_ERROR_INVALID_STATE: - return_err_code = err_code; - break; - default: - return_err_code = NRF_ERROR_INTERNAL; - break; - } - - if (send_events) - { - events_send_from_err_code(conn_handle, err_code, p_sec_params); - } - - return return_err_code; -} - - -/**@brief Function for requesting security parameters from the user and passing them to the security_dispatcher. - * - * @param[in] conn_handle The connection that needs security parameters. - * @param[in] p_peer_params The peer's security parameters if present. Otherwise NULL. - */ -static void smd_params_reply_perform(uint16_t conn_handle, ble_gap_sec_params_t const * p_peer_params) -{ - ret_code_t err_code; - sec_params_reply_context_t context = new_context_get(); - - params_req_send(conn_handle, p_peer_params, &context); - - err_code = smd_params_reply(conn_handle, context.p_sec_params, m_p_public_key); - - flags_set_from_err_code(conn_handle, err_code, true); - events_send_from_err_code(conn_handle, err_code, context.p_sec_params); -} - - -/**@brief Function for handling @ref PM_EVT_CONN_SEC_PARAMS_REQ events. - * - * @param[in] p_event The @ref PM_EVT_CONN_SEC_PARAMS_REQ event. - */ -static __INLINE void params_req_process(pm_evt_t const * p_event) -{ - smd_params_reply_perform(p_event->conn_handle, p_event->params.conn_sec_params_req.p_peer_params); -} - - -/**@brief Function for handling @ref PM_EVT_SLAVE_SECURITY_REQ events. - * - * @param[in] p_event The @ref PM_EVT_SLAVE_SECURITY_REQ event. - */ -static void sec_req_process(pm_evt_t const * p_event) -{ - bool null_params = false; - if (mp_sec_params == NULL) - { - null_params = true; - } - else if ((bool)m_sec_params.bond < (bool)p_event->params.slave_security_req.bond) - { - null_params = true; - } - else if ((bool)m_sec_params.mitm < (bool)p_event->params.slave_security_req.mitm) - { - null_params = true; - } - else - { - // No action. - } - ret_code_t err_code = link_secure(p_event->conn_handle, null_params, false, true); - UNUSED_VARIABLE(err_code); // It is acceptable to ignore the return code because it is - // acceptable to ignore a security request. -} - - -/**@brief Function for translating an SMD event to an SM event and passing it on to SM event handlers. - * - * @param[in] p_event The event to forward. - */ -static void evt_forward(pm_evt_t * p_event) -{ - evt_send(p_event); -} - - -/**@brief Event handler for events from the Security Dispatcher module. - * This handler is extern in Security Dispatcher. - * - * @param[in] p_event The event that has happened. - */ -void sm_smd_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_CONN_SEC_PARAMS_REQ: - params_req_process(p_event); - break; - case PM_EVT_SLAVE_SECURITY_REQ: - sec_req_process(p_event); - /* fallthrough */ - default: - // Forward the event to all registered Security Manager event handlers. - evt_forward(p_event); - break; - } -} - - -/**@brief Function for checking our user flags for pending calls to @ref smd_link_secure. - * - * @details This function will attempt to perform any pending calls. - * - * @param[in] flag_id The user flag to check. Must be either @ref m_flag_link_secure_pending_busy - * or @ref m_flag_link_secure_pending_flash_full. - */ -static void link_secure_pending_process(ble_conn_state_user_flag_id_t flag_id) -{ - sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); - if (sdk_mapped_flags_any_set(flag_collection)) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); - if (pending) - { - bool force_repairing = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_force_repairing); - bool null_params = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_flag_link_secure_null_params); - - ret_code_t err_code = link_secure(conn_handle_list.flag_keys[i], null_params, force_repairing, true); // If this fails, it will be automatically retried. - UNUSED_VARIABLE(err_code); - } - } - } -} - - -/**@brief Function for checking our user flags for pending calls to @ref smd_params_reply. - * - * @details This function will attempt to perform any pending calls. - * - * @param[in] flag_id The user flag to check. Must be either @ref m_flag_params_reply_pending_busy - * or @ref m_flag_params_reply_pending_flash_full. - */ -static void params_reply_pending_process(ble_conn_state_user_flag_id_t flag_id) -{ - sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id); - if (sdk_mapped_flags_any_set(flag_collection)) - { - sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles(); - - for (uint32_t i = 0; i < conn_handle_list.len; i++) - { - bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id); - if (pending) - { - smd_params_reply_perform(conn_handle_list.flag_keys[i], NULL); - } - } - } -} - - -/**@brief Event handler for events from the Peer Database module. - * This handler is extern in Peer Database. - * - * @param[in] p_event The event that has happened. - */ -void sm_pdb_evt_handler(pm_evt_t * p_event) -{ - switch (p_event->evt_id) - { - case PM_EVT_FLASH_GARBAGE_COLLECTED: - params_reply_pending_process(m_flag_params_reply_pending_flash_full); - link_secure_pending_process(m_flag_link_secure_pending_flash_full); - /* fallthrough */ - case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: - case PM_EVT_PEER_DATA_UPDATE_FAILED: - case PM_EVT_PEER_DELETE_SUCCEEDED: - case PM_EVT_PEER_DELETE_FAILED: - params_reply_pending_process(m_flag_params_reply_pending_busy); - link_secure_pending_process(m_flag_link_secure_pending_busy); - break; - default: - // Do nothing. - break; - } -} - - -/**@brief Funtion for initializing a BLE Connection State user flag. - * - * @param[out] flag_id The flag to initialize. - */ -static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id) -{ - if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID) - { - *p_flag_id = ble_conn_state_user_flag_acquire(); - } -} - - -ret_code_t sm_init(void) -{ - NRF_PM_DEBUG_CHECK(!m_module_initialized); - - flag_id_init(&m_flag_link_secure_pending_busy); - flag_id_init(&m_flag_link_secure_pending_flash_full); - flag_id_init(&m_flag_link_secure_force_repairing); - flag_id_init(&m_flag_link_secure_null_params); - flag_id_init(&m_flag_params_reply_pending_busy); - flag_id_init(&m_flag_params_reply_pending_flash_full); - - if (m_flag_params_reply_pending_flash_full == BLE_CONN_STATE_USER_FLAG_INVALID) - { - return NRF_ERROR_INTERNAL; - } - - m_module_initialized = true; - - return NRF_SUCCESS; -} - - -void sm_ble_evt_handler(ble_evt_t const * p_ble_evt) -{ - NRF_PM_DEBUG_CHECK(p_ble_evt != NULL); - - smd_ble_evt_handler(p_ble_evt); - link_secure_pending_process(m_flag_link_secure_pending_busy); -} - - -/**@brief Funtion for checking whether security parameters are valid. - * - * @param[out] p_sec_params The security parameters to verify. - * - * @return Whether the security parameters are valid. - */ -static bool sec_params_verify(ble_gap_sec_params_t * p_sec_params) -{ - // NULL check. - if (p_sec_params == NULL) - { - return false; - } - - // OOB not allowed unless MITM. - if (!p_sec_params->mitm && p_sec_params->oob) - { - return false; - } - - // IO Capabilities must be one of the valid values from @ref BLE_GAP_IO_CAPS. - if (p_sec_params->io_caps > BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY) - { - return false; - } - - // Must have either IO capabilities or OOB if MITM. - if (p_sec_params->mitm && (p_sec_params->io_caps == BLE_GAP_IO_CAPS_NONE) && !p_sec_params->oob) - { - return false; - } - - // Minimum key size cannot be larger than maximum key size. - if (p_sec_params->min_key_size > p_sec_params->max_key_size) - { - return false; - } - - // Key size cannot be below 7 bytes. - if (p_sec_params->min_key_size < 7) - { - return false; - } - - // Key size cannot be above 16 bytes. - if (p_sec_params->max_key_size > 16) - { - return false; - } - - // Signing is not supported. - if (p_sec_params->kdist_own.sign || p_sec_params->kdist_peer.sign) - { - return false; - } - - // link bit must be 0. - if (p_sec_params->kdist_own.link || p_sec_params->kdist_peer.link) - { - return false; - } - - // If bonding is not enabled, no keys can be distributed. - if (!p_sec_params->bond && ( p_sec_params->kdist_own.enc - || p_sec_params->kdist_own.id - || p_sec_params->kdist_peer.enc - || p_sec_params->kdist_peer.id)) - { - return false; - } - - // If bonding is enabled, one or more keys must be distributed. - if ( p_sec_params->bond - && !p_sec_params->kdist_own.enc - && !p_sec_params->kdist_own.id - && !p_sec_params->kdist_peer.enc - && !p_sec_params->kdist_peer.id) - { - return false; - } - - return true; -} - - -ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - if (p_sec_params == NULL) - { - mp_sec_params = NULL; - m_sec_params_set = true; - return NRF_SUCCESS; - } - else if (sec_params_verify(p_sec_params)) - { - m_sec_params = *p_sec_params; - mp_sec_params = &m_sec_params; - m_sec_params_set = true; - return NRF_SUCCESS; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } -} - - -void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - NRF_PM_DEBUG_CHECK(p_conn_sec_config != NULL); - - smd_conn_sec_config_reply(conn_handle, p_conn_sec_config); -} - - -ret_code_t sm_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - VERIFY_PARAM_NOT_NULL(p_context); - - sec_params_reply_context_t * p_sec_params_reply_context = (sec_params_reply_context_t *)p_context; - if (p_sec_params == NULL) - { - // Set the store pointer to NULL, so that NULL is passed to the SoftDevice. - p_sec_params_reply_context->p_sec_params = NULL; - } - else if (sec_params_verify(p_sec_params)) - { - // Copy the provided sec_params into the store. - p_sec_params_reply_context->sec_params_mem = *p_sec_params; - p_sec_params_reply_context->p_sec_params = &p_sec_params_reply_context->sec_params_mem; - } - else - { - return NRF_ERROR_INVALID_PARAM; - } - p_sec_params_reply_context->params_reply_called = true; - - return NRF_SUCCESS; -} - - -ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key) -{ - NRF_PM_DEBUG_CHECK(m_module_initialized); - - m_p_public_key = p_public_key; - - return NRF_SUCCESS; -} - - -ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing) -{ - ret_code_t ret; - - NRF_PM_DEBUG_CHECK(m_module_initialized); - - ret = link_secure(conn_handle, false, force_repairing, false); - return ret; -} -#endif // NRF_MODULE_ENABLED(PEER_MANAGER) diff --git a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h b/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h deleted file mode 100644 index dda231cb72..0000000000 --- a/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_14_2/TARGET_SOFTDEVICE_COMMON/ble/peer_manager/security_manager.h +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form, except as embedded into a Nordic - * Semiconductor ASA integrated circuit in a product or a software update for - * such product, must reproduce the above copyright notice, this list of - * conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of Nordic Semiconductor ASA nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 4. This software, with or without modification, must only be used with a - * Nordic Semiconductor ASA integrated circuit. - * - * 5. Any software provided in binary form under this license must not be reverse - * engineered, decompiled, modified and/or disassembled. - * - * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ -#ifndef SECURITY_MANAGER_H__ -#define SECURITY_MANAGER_H__ - -#include -#include "sdk_errors.h" -#include "nrf_ble.h" -#include "ble_gap.h" -#include "peer_manager_types.h" -#include "security_dispatcher.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @cond NO_DOXYGEN - * @defgroup security_manager Security Manager - * @ingroup peer_manager - * @{ - * @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and - * encryption, including flash storage of shared data. - */ - - -/**@brief Function for initializing the Security Manager module. - * - * @retval NRF_SUCCESS If initialization was successful. - * @retval NRF_ERROR_INTERNAL If an unexpected error occurred. - */ -ret_code_t sm_init(void); - - -/**@brief Function for dispatching SoftDevice events to the Security Manager module. - * - * @param[in] ble_evt The SoftDevice event. - */ -void sm_ble_evt_handler(ble_evt_t const * ble_evt); - - -/**@brief Function for providing pairing and bonding parameters to use for pairing procedures. - * - * @details Until this is called, all bonding procedures initiated by the peer will be rejected. - * This function can be called multiple times, even with NULL p_sec_params, in which case - * it will go back to rejecting all procedures. - * - * @param[in] p_sec_params The security parameters to use for this link. Can be NULL to reject - * all pairing procedures. - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters. - */ -ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params); - - -/**@brief Function for providing security configuration for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it - * is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t - * for the value of the default. - * - * @param[in] conn_handle The connection to set the configuration for. - * @param[in] p_conn_sec_config The configuration. - */ -void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config); - - -/**@brief Function for providing security parameters for a link. - * - * @details This function is optional, and must be called in reply to a @ref - * PM_EVT_CONN_SEC_PARAMS_REQ event, before the Security Manager event handler returns. If - * it is not called in time, the parameters given in @ref sm_sec_params_set are used. See - * @ref pm_conn_sec_config_t for the value of the default. - * - * @param[in] conn_handle The connection to set the parameters for. - * @param[in] p_sec_params The parameters. If NULL, the security procedure is rejected. - * @param[in] p_context The context found in the request event that this function replies to. - * - * @retval NRF_SUCCESS Successful reply. - * @retval NRF_ERROR_NULL p_context was null. - * @retval NRF_ERROR_INVALID_PARAM Value of p_sec_params was invalid. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t sm_sec_params_reply(uint16_t conn_handle, - ble_gap_sec_params_t * p_sec_params, - void const * p_context); - - -/**@brief Experimental function for specifying the public key to use for LESC operations. - * - * @details This function can be called multiple times. The specified public key will be used for - * all subsequent LESC (LE Secure Connections) operations until the next time this function - * is called. - * - * @note The key must continue to reside in application memory as it is not copied by Peer Manager. - * - * @param[in] p_public_key The public key to use for all subsequent LESC operations. - * - * @retval NRF_SUCCESS Pairing initiated successfully. - * @retval NRF_ERROR_INVALID_STATE This module is not initialized. - */ -ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key); - - - -/**@brief Function for initiating security on the link, with the specified parameters. - * - * @note If the connection is a peripheral connection, this will send a security request to the - * master, but the master is not obligated to initiate pairing or encryption in response. - * @note If the connection is a central connection and a key is available, the parameters will be - * used to determine whether to re-pair or to encrypt using the existing key. If no key is - * available, pairing will be started. - * - * @param[in] conn_handle Handle of the connection to initiate pairing on. - * @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether - * an encryption key already exists. This argument is only relevant for - * the central role. Recommended value: false - * - * @retval NRF_SUCCESS Success. - * @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations - * can be performed on this link. - * @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle. - * @retval NRF_ERROR_NOT_FOUND Security parameters have not been set. - * @retval NRF_ERROR_INVALID_STATE A security procedure is already in progress on the link, - * or the link is disconnecting. - * @retval NRF_ERROR_INTERNAL An unexpected error occurred. - */ -ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing); - -/** @} - * @endcond - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* SECURITY_MANAGER_H__ */ From 2cb6e659a9d15223d0adbfc65d73b485e86df707 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 15 May 2018 15:11:33 +0100 Subject: [PATCH 224/274] Nordic BLE: Backport security fixes from nRF5 to nRF5x --- .../source/btle/custom/custom_helper.cpp | 87 +++++----- .../source/btle/custom/custom_helper.h | 8 +- .../TARGET_NRF5x/source/nRF5xGattServer.cpp | 153 ++++++++++-------- .../source/nRF5xPalSecurityManager.cpp | 4 + .../source/nRF5xPalSecurityManager.h | 4 + 5 files changed, 136 insertions(+), 120 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp index ea6e63c74c..95be197637 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.cpp @@ -31,6 +31,32 @@ typedef struct { static unsigned uuidTableEntries = 0; /* current usage of the table */ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES]; +namespace { + +static void set_perm(ble_gap_conn_sec_mode_t& dest, GattAttribute::Security_t src) { + switch (src.value()) { + case GattAttribute::Security_t::NONE: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&dest); + break; + + case GattAttribute::Security_t::UNAUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&dest); + break; + + case GattAttribute::Security_t::AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&dest); + break; + + case GattAttribute::Security_t::SC_AUTHENTICATED: + BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(&dest); + break; + + default: + break; + } +} + +} void custom_reset_128bits_uuid_table() { uuidTableEntries = 0; } @@ -204,7 +230,9 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base, error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -227,8 +255,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Notification requires cccd */ memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t)); cccd_md.vloc = BLE_GATTS_VLOC_STACK; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + set_perm(cccd_md.read_perm, GattAttribute::Security_t::NONE); + set_perm(cccd_md.write_perm, update_security); } ble_gatts_char_md_t char_md = {0}; @@ -257,49 +285,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle, /* Always set variable size */ attr_md.vlen = has_variable_len; - if (char_props.read || char_props.notify || char_props.indicate) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm); - break; - default: - break; - }; - } - - if (char_props.write || char_props.write_wo_resp) { - switch (requiredSecurity) { - case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK : - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm); - break; - case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM : - BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm); - break; - default: - break; - }; - } + set_perm(attr_md.read_perm, read_security); + set_perm(attr_md.write_perm, write_security); ble_gatts_attr_t attr_char_value = {0}; @@ -343,7 +330,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle) + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security) { /* Descriptor metadata */ ble_gatts_attr_md_t desc_md = {0}; @@ -353,8 +342,8 @@ error_t custom_add_in_descriptor(uint16_t char_handle, desc_md.vlen = has_variable_len; /* Make it readable and writable */ - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm); + set_perm(desc_md.read_perm, read_security); + set_perm(desc_md.write_perm, write_security); ble_gatts_attr_t attr_desc = {0}; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h index 49505c5eec..e5cddc2bd5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/btle/custom/custom_helper.h @@ -42,7 +42,9 @@ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid); error_t custom_add_in_characteristic(uint16_t service_handle, ble_uuid_t *p_uuid, uint8_t properties, - SecurityManager::SecurityMode_t requiredSecurity, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security, + GattAttribute::Security_t update_security, uint8_t *p_data, uint16_t length, uint16_t max_length, @@ -61,7 +63,9 @@ error_t custom_add_in_descriptor(uint16_t char_handle, uint16_t length, uint16_t max_length, bool has_variable_len, - uint16_t *p_desc_handle); + uint16_t *p_desc_handle, + GattAttribute::Security_t read_security, + GattAttribute::Security_t write_security); #ifdef __cplusplus } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp index f606d541a0..8c93ac118c 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xGattServer.cpp @@ -29,38 +29,38 @@ namespace { static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID_OFFSET } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 0 + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 0 } } }; static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_ATTERR_INVALID + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_ATTERR_INVALID } } }; @@ -164,10 +164,13 @@ ble_error_t nRF5xGattServer::addService(GattService &service) } ASSERT_TRUE ( ERROR_NONE == - custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, + custom_add_in_characteristic( + BLE_GATT_HANDLE_INVALID, &nordicUUID, p_char->getProperties(), - p_char->getRequiredSecurity(), + p_char->getReadSecurityRequirement(), + p_char->getWriteSecurityRequirement(), + p_char->getUpdateSecurityRequirement(), p_char->getValueAttribute().getValuePtr(), p_char->getValueAttribute().getLength(), p_char->getValueAttribute().getMaxLength(), @@ -178,7 +181,8 @@ ble_error_t nRF5xGattServer::addService(GattService &service) presentationFormatDescriptorValueLen, p_char->isReadAuthorizationEnabled(), p_char->isWriteAuthorizationEnabled(), - &nrfCharacteristicHandles[characteristicCount]), + &nrfCharacteristicHandles[characteristicCount] + ), BLE_ERROR_PARAM_OUT_OF_RANGE ); /* Update the characteristic handle */ @@ -218,7 +222,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service) p_desc->getLength(), p_desc->getMaxLength(), p_desc->hasVariableLength(), - &nrfDescriptorHandles[descriptorCount]), + &nrfDescriptorHandles[descriptorCount], + p_desc->getReadSecurityRequirement(), + p_desc->getWriteSecurityRequirement()), BLE_ERROR_PARAM_OUT_OF_RANGE); p_descriptors[descriptorCount] = p_desc; @@ -260,9 +266,9 @@ ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { - .len = *lengthP, - .offset = 0, - .p_value = buffer, + /* .len = */ *lengthP, + /* .offset = */ 0, + /* .p_value = */ buffer, }; ASSERT_TRUE( ERROR_NONE == @@ -302,9 +308,9 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute ble_error_t returnValue = BLE_ERROR_NONE; ble_gatts_value_t value = { - .len = len, - .offset = 0, - .p_value = const_cast(buffer), + /* .len = */ len, + /* .offset = */ 0, + /* .p_value = */ const_cast(buffer), }; if (localOnly) { @@ -345,7 +351,16 @@ ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute } } - if (updatesEnabled) { + bool updates_permitted = false; + ble_gap_conn_sec_t connection_security; + uint32_t err = sd_ble_gap_conn_sec_get(connectionHandle, &connection_security); + if (!err && + (connection_security.sec_mode.sm == 1) && + (connection_security.sec_mode.lv >= p_characteristics[characteristicIndex]->getUpdateSecurityRequirement().value())) { + updates_permitted = true; + } + + if (updatesEnabled && updates_permitted) { error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); if (error != ERROR_NONE) { switch (error) { @@ -618,14 +633,14 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) // success, signal it to the softdevice ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = BLE_GATT_STATUS_SUCCESS, - .update = 1, - .offset = input_req.offset, - .len = input_req.len, - .p_data = input_req.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, + /* .update = */ 1, + /* .offset = */ input_req.offset, + /* .len = */ input_req.len, + /* .p_data = */ input_req.data } } }; @@ -646,12 +661,12 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = conn_handle, - .handle = req->attr_handle, - .offset = req->offset, - .len = req->length, - .data = req->data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ conn_handle, + /* .handle = */ req->attr_handle, + /* .offset = */ req->offset, + /* .len = */ req->length, + /* .data = */ req->data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; @@ -668,9 +683,9 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) // FIXME can't use ::write here, this function doesn't take the offset into account ... ble_gatts_value_t value = { - .len = req->length, - .offset = req->offset, - .p_value = req->data + /* .len = */ req->length, + /* .offset = */ req->offset, + /* .p_value = */ req->data }; uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value); if (update_err) { @@ -695,25 +710,25 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } GattWriteAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.write.offset, - .len = gattsEventP->params.authorize_request.request.write.len, - .data = gattsEventP->params.authorize_request.request.write.data, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, + /* .len = */ gattsEventP->params.authorize_request.request.write.len, + /* .data = */ gattsEventP->params.authorize_request.request.write.data, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, - .params = { - .write = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), - .update = 1, - .offset = cbParams.offset, - .len = cbParams.len, - .p_data = cbParams.data + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, + /* .params = */ { + /* .write = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), + /* .update = */ 1, + /* .offset = */ cbParams.offset, + /* .len = */ cbParams.len, + /* .p_data = */ cbParams.data } } }; @@ -747,21 +762,21 @@ void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) } case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { GattReadAuthCallbackParams cbParams = { - .connHandle = gattsEventP->conn_handle, - .handle = handle_value, - .offset = gattsEventP->params.authorize_request.request.read.offset, - .len = 0, - .data = NULL, - .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member + /* .connHandle = */ gattsEventP->conn_handle, + /* .handle = */ handle_value, + /* .offset = */ gattsEventP->params.authorize_request.request.read.offset, + /* .len = */ 0, + /* .data = */ NULL, + /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { - .type = BLE_GATTS_AUTHORIZE_TYPE_READ, - .params = { - .read = { - .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) + /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_READ, + /* .params = */ { + /* .read = */ { + /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeRead(&cbParams) } } }; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp index 9b608c768e..815b006817 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.cpp @@ -616,6 +616,10 @@ ble_error_t nRF5xSecurityManager::set_peer_csrk( return BLE_ERROR_NOT_IMPLEMENTED; } +ble_error_t nRF5xSecurityManager::remove_peer_csrk(connection_handle_t connection) +{ + return BLE_ERROR_NOT_IMPLEMENTED; +} //////////////////////////////////////////////////////////////////////////// // Authentication // diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h index e88e9075f9..aa2ab2d2df 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5x/source/nRF5xPalSecurityManager.h @@ -284,6 +284,10 @@ public: sign_count_t sign_counter ); + /** + * @see ::ble::pal::SecurityManager::remove_peer_csrk + */ + virtual ble_error_t remove_peer_csrk(connection_handle_t connection); //////////////////////////////////////////////////////////////////////////// // Authentication 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 225/274] 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 288c3952d80e6960c9707bfafda8893c02fcc884 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Tue, 15 May 2018 18:37:50 +0100 Subject: [PATCH 226/274] Address Paul's comments --- features/FEATURE_BLE/ble/generic/GenericGap.h | 9 ++++++- .../FEATURE_BLE/source/generic/GenericGap.cpp | 26 +++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index d18814adc7..18e9196b6e 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -340,7 +340,14 @@ private: void on_unexpected_error(const pal::GapUnexpectedErrorEvent &e); - pal::own_address_type_t get_own_address_type(bool central_not_peripheral, bool non_connectable_or_scan_request); + enum AddressUseType_t { + CENTRAL_CONNECTION, + CENTRAL_SCAN, + PERIPHERAL_CONNECTABLE, + PERIPHERAL_NON_CONNECTABLE + }; + + pal::own_address_type_t get_own_address_type(AddressUseType_t address_use_type); bool initialize_whitelist() const; diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 59f315bfb0..b00ad941ab 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -548,7 +548,7 @@ ble_error_t GenericGap::connect( _initiator_policy_mode, (pal::connection_peer_address_type_t::type) peerAddrType, ble::address_t(peerAddr), - get_own_address_type(true /* central */, false /* requires resolvable address */), + get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */), connectionParams->minConnectionInterval, connectionParams->maxConnectionInterval, connectionParams->slaveLatency, @@ -836,7 +836,7 @@ ble_error_t GenericGap::startRadioScan(const GapScanningParams &scanningParams) return BLE_ERROR_INVALID_STATE; } - pal::own_address_type_t own_address_type = get_own_address_type(true /* central */, true /* can use non resolvable address for scan requests */); + pal::own_address_type_t own_address_type = get_own_address_type(CENTRAL_SCAN /* central, can use non resolvable address for scan requests */); if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) { @@ -952,8 +952,12 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) return BLE_ERROR_INVALID_PARAM; } - pal::own_address_type_t own_address_type = get_own_address_type(false /* peripheral */, - params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED /* we can only use non resolvable addresses int this case */); + // We can only use non resolvable addresses if the device is non connectable + AddressUseType_t address_use_type = + ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) + || (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) + ? PERIPHERAL_NON_CONNECTABLE : PERIPHERAL_CONNECTABLE; + pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) { @@ -1276,18 +1280,18 @@ void GenericGap::on_unexpected_error(const pal::GapUnexpectedErrorEvent& e) // has been updated. } -pal::own_address_type_t GenericGap::get_own_address_type(bool central_not_peripheral, bool non_connectable_or_scan_request) +pal::own_address_type_t GenericGap::get_own_address_type(AddressUseType_t address_use_type) { if(_privacy_enabled) { - bool can_use_non_resolvable_address = false; - if(central_not_peripheral) { - can_use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; - } else { - can_use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; + bool use_non_resolvable_address = false; + if(address_use_type == CENTRAL_SCAN) { + use_non_resolvable_address = _central_privacy_configuration.use_non_resolvable_random_address; + } else if (address_use_type == PERIPHERAL_NON_CONNECTABLE) { + use_non_resolvable_address = _peripheral_privacy_configuration.use_non_resolvable_random_address; } // An non resolvable private address should be generated - if(non_connectable_or_scan_request && can_use_non_resolvable_address) { + if(use_non_resolvable_address) { return pal::own_address_type_t::RANDOM_ADDRESS; } 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 227/274] 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 228/274] 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 229/274] 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; From 1fdb57e82c04836de86cbfd498a2e0c726257fad Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Wed, 16 May 2018 12:02:21 +0100 Subject: [PATCH 230/274] Removed set_privacy() API and added is_privacy_supported() check to PAL + Generic GAP --- features/FEATURE_BLE/ble/pal/PalGap.h | 10 +++------- features/FEATURE_BLE/source/generic/GenericGap.cpp | 13 +++++++++++-- .../targets/TARGET_CORDIO/CordioPalGap.h | 11 +++-------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/PalGap.h b/features/FEATURE_BLE/ble/pal/PalGap.h index 5f7865d8f2..aec629a587 100644 --- a/features/FEATURE_BLE/ble/pal/PalGap.h +++ b/features/FEATURE_BLE/ble/pal/PalGap.h @@ -649,17 +649,13 @@ struct Gap { disconnection_reason_t disconnection_reason ) = 0; - /** Enable or disable privacy feature - * @param enable whether to enable privacy feature + /** Check if privacy feature is supported by implementation * - * @return BLE_ERROR_NONE if the request has been successfully sent or the - * appropriate error otherwise. + * @return true if privacy is supported, false otherwise. * * @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature. */ - virtual ble_error_t set_privacy( - bool enable - ) = 0; + virtual bool is_privacy_supported() = 0; /** Enable or disable private addresses resolution * diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index b00ad941ab..c1f47f0f8d 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -881,9 +881,18 @@ ble_error_t GenericGap::initRadioNotification(void) ble_error_t GenericGap::enablePrivacy(bool enable) { - _privacy_enabled = enable; + if(enable == _privacy_enabled) { + // No change + return BLE_ERROR_NONE; + } - _pal_gap.set_privacy(enable); + if(enable && !_pal_gap.is_privacy_supported()) + { + // Privacy is not supported by the implementation + return BLE_ERROR_NOT_IMPLEMENTED; + } + + _privacy_enabled = enable; update_address_resolution_setting(); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index bb41b19b2c..ee2c4f2f57 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -308,13 +308,9 @@ public: return BLE_ERROR_NONE; } - virtual ble_error_t set_privacy( - bool enable - ) { - // - - - return BLE_ERROR_NONE; + virtual bool is_privacy_supported() { + // We only support controller-based privacy, so return whether the controller supports it + return HciLlPrivacySupported(); } virtual ble_error_t set_address_resolution( @@ -481,7 +477,6 @@ private: }; private: - address_t device_random_static_identity_address; address_t device_random_address; bool use_active_scanning; }; From 7ef7ef553cad50e40c462503bf4f1cbd00fcd882 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Wed, 16 May 2018 12:04:04 +0100 Subject: [PATCH 231/274] Fix is_random_xxx_address() functions in GenericGap that I had broken :) --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index c1f47f0f8d..faa78eb4d3 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -230,7 +230,7 @@ static bool is_prand_24_bits_valid(const BLEProtocol::AddressBytes_t address) static bool is_random_static_address(const BLEProtocol::AddressBytes_t address) { // top two msb bits shall be equal to 0b11. - if (((address[5] >> 6) & 0xC0) != 0xC0) { + if ((address[5] & 0xC0) != 0xC0) { return false; } @@ -244,7 +244,7 @@ static bool is_random_private_non_resolvable_address( const BLEProtocol::AddressBytes_t address ) { // top two msb bits shall be equal to 0b00. - if (((address[5] >> 6) & 0xC0) != 0x00) { + if ((address[5] & 0xC0) != 0x00) { return false; } @@ -258,7 +258,7 @@ static bool is_random_private_resolvable_address( const BLEProtocol::AddressBytes_t address ) { // top two msb bits shall be equal to 0b01. - if (((address[5] >> 6) & 0xC0) != 0x40) { + if ((address[5] & 0xC0) != 0x40) { return false; } From ad09ba0dccca95077e145f46c36d88d63a2d0fa3 Mon Sep 17 00:00:00 2001 From: Donatien Garnier Date: Wed, 16 May 2018 13:54:25 +0100 Subject: [PATCH 232/274] Fix handling of security escalation in on_connection_complete() --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index faa78eb4d3..12bcd14c48 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -1235,11 +1235,12 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e // Now starts pairing or authentication procedures if required if(needs_pairing) { SecurityManager &sm = createBLEInstance()->getSecurityManager(); - sm.requestPairing(e.connection_handle); + // Request authentication to start pairing procedure + sm.requestAuthentication(e.connection_handle); } else if(needs_authentication) { - SecurityManager &sm = createBLEInstance()->getSecurityManager(); - sm.requestAuthentication(e.connection_handle); + // TODO: GAP Authentication != Security Manager authentication + // Needs to be implemented } } else { // for now notify user that the connection failled by issuing a timeout From 37c036ca6b508af089be1730d3c9de3f136a3708 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 16 May 2018 14:42:44 +0100 Subject: [PATCH 233/274] Nordic: Port privacy to softdevice v4. Many things have changed; the identity list isn't shared anymore with the whitelist and resolution is handled by the stack itself. --- .../TARGET_NRF52/source/nRF5xGap.cpp | 102 ++++++++++++------ .../TARGET_NRF52/source/nRF5xGap.h | 1 + .../source/nRF5xPalSecurityManager.cpp | 59 +++------- .../source/nRF5xPalSecurityManager.h | 31 +----- 4 files changed, 89 insertions(+), 104 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 71f40f8b45..9b85b6d6ae 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -28,7 +28,6 @@ #include "nRF5xPalSecurityManager.h" using ble::pal::vendor::nordic::nRF5xSecurityManager; -typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; using ble::ArrayView; using ble::pal::advertising_peer_address_type_t; @@ -316,6 +315,20 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) } } adv_para.p_whitelist = &whitelist; +#else + if (_privacy_enabled) { + bool enable_resolution = + _peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE; + update_identities_list(enable_resolution); + + if (_peripheral_privacy_configuration.use_non_resolvable_random_address && + is_advertising_non_connectable(params) + ) { + set_private_non_resolvable_address(); + } else { + set_private_resolvable_address(); + } + } #endif /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ @@ -384,7 +397,13 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */ scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */ + if (_privacy_enabled) { + bool enable_resolution = + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE; + + update_identities_list(enable_resolution); + if (_central_privacy_configuration.use_non_resolvable_random_address) { set_private_non_resolvable_address(); } else { @@ -524,7 +543,15 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, } else { addr.addr_id_peer = 0; } - + + if (_privacy_enabled) { + bool enable_resolution = + _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE; + + update_identities_list(enable_resolution); + set_private_resolvable_address(); + } + #endif if (scanParamsIn != NULL) { @@ -1201,6 +1228,37 @@ void nRF5xGap::processDisconnectionEvent( ); } +ble_error_t nRF5xGap::update_identities_list(bool resolution_enabled) +{ + uint32_t err; + + if (resolution_enabled) { + ArrayView entries = get_sm().get_resolving_list(); + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + ble_gap_id_key_t* id_keys_pp[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; + + for (size_t i = 0; i < limit; ++i) { + id_keys_pp[i] = &entries[i]; + } + + err = sd_ble_gap_device_identities_set( + limit ? id_keys_pp : NULL, + /* use the local IRK for all devices */ NULL, + limit + ); + } else { + err = sd_ble_gap_device_identities_set( + NULL, + /* use the local IRK for all devices */ NULL, + 0 + ); + } + + return err ? BLE_ERROR_INVALID_STATE : BLE_ERROR_NONE; +} + void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { using BLEProtocol::AddressType; @@ -1246,14 +1304,8 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t if (private_peer_known) { - // FIXME: Is this correct for SD > 2 ? - const resolving_list_entry_t* entry = get_sm().resolve_address( - evt.peer_addr.addr - ); - MBED_ASSERT(entry == NULL); - - peer_addr_type = convert_identity_address(entry->peer_identity_address_type); - peer_address = entry->peer_identity_address.data(); + peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);; + peer_address = evt.peer_addr.addr; peer_resolvable_address = evt.peer_addr.addr; } else { if (_privacy_enabled && @@ -1294,7 +1346,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t ) { switch (_peripheral_privacy_configuration.resolution_strategy) { case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: - nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle); + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle); break; case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: @@ -1322,32 +1374,16 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { using BLEProtocol::AddressType; - AddressType_t peer_addr_type; - const uint8_t* peer_address = evt.peer_addr.addr; - if (_privacy_enabled && - evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && - _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE + evt.peer_addr.addr_id_peer == 0 && + _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER ) { - using ble::pal::vendor::nordic::nRF5xSecurityManager; - - const resolving_list_entry_t* entry = get_sm().resolve_address( - peer_address - ); - - if (entry) { - peer_address = entry->peer_identity_address.data(); - peer_addr_type = convert_identity_address(entry->peer_identity_address_type); - } else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) { - peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); - } else { - // filter out the packet. - return; - } - } else { - peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + return; } + AddressType_t peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + const uint8_t* peer_address = evt.peer_addr.addr; + processAdvertisementReport( peer_address, evt.rssi, diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index 622588670d..d019d99cdc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -267,6 +267,7 @@ private: friend void btle_handler(const ble_evt_t *p_ble_evt); friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context); + ble_error_t update_identities_list(bool resolution_enabled); void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt); void on_advertising_packet(const ble_gap_evt_adv_report_t &evt); uint16_t m_connectionHandle; diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp index 815b006817..9a48de2267 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.cpp @@ -158,10 +158,18 @@ ble_error_t nRF5xSecurityManager::add_device_to_resolving_list( return BLE_ERROR_INVALID_STATE; } - resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count]; - entry.peer_identity_address_type = peer_identity_address_type; - entry.peer_identity_address = peer_identity_address; - entry.peer_irk = peer_irk; + ble_gap_id_key_t& entry = resolving_list[resolving_list_entry_count]; + entry.id_addr_info.addr_type = peer_identity_address_type.value(); + memcpy( + entry.id_addr_info.addr, + peer_identity_address.data(), + peer_identity_address.size() + ); + memcpy( + entry.id_info.irk, + peer_irk.data(), + peer_irk.size() + ); ++resolving_list_entry_count; @@ -176,9 +184,9 @@ ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list( // first the index needs to be found for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) { - resolving_list_entry_t& entry = resolving_list[entry_index]; - if (entry.peer_identity_address_type == peer_identity_address_type && - entry.peer_identity_address == peer_identity_address + ble_gap_id_key_t& entry = resolving_list[entry_index]; + if (entry.id_addr_info.addr_type == peer_identity_address_type.value() && + entry.id_addr_info.addr == peer_identity_address ) { break; } @@ -204,46 +212,13 @@ ble_error_t nRF5xSecurityManager::clear_resolving_list() return BLE_ERROR_NONE; } -ArrayView -nRF5xSecurityManager::get_resolving_list() { - return ArrayView( +ArrayView nRF5xSecurityManager::get_resolving_list() { + return ArrayView( resolving_list, resolving_list_entry_count ); } -const nRF5xSecurityManager::resolving_list_entry_t* -nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { -#if defined(MBEDTLS_ECDH_C) - typedef byte_array_t hash_t; - - for (size_t i = 0; i < resolving_list_entry_count; ++i) { - resolving_list_entry_t& entry = resolving_list[i]; - hash_t hash_generated; - - // Compute the hash part from the random address part when the irk of - // the entry is used - _crypto.ah( - make_const_ArrayView(entry.peer_irk), - make_const_ArrayView( - resolvable_address.data() + CryptoToolbox::hash_size_ - ), - make_ArrayView(hash_generated) - ); - - // Compare hash generated with the hash present in the address passed as - // parameter. If they are equal then the IRK of the entry has been used - // to generate the resolvable address. - if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) { - return &entry; - } - } -#endif - return NULL; -} - - - //////////////////////////////////////////////////////////////////////////// // Pairing // diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h index aa2ab2d2df..30ac7e20cc 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xPalSecurityManager.h @@ -84,39 +84,12 @@ public: */ virtual ble_error_t clear_resolving_list(); - /** - * An entry of the resolving list stored in the SecurityManager. - */ - struct resolving_list_entry_t { - resolving_list_entry_t() : - peer_identity_address_type( - advertising_peer_address_type_t::PUBLIC_ADDRESS - ) - { } - - irk_t peer_irk; - address_t peer_identity_address; - advertising_peer_address_type_t peer_identity_address_type; - }; - /** * Return the IRKs present in the resolving list * @param count The number of entries present in the resolving list. * @param pointer to the first entry of the resolving list. */ - ArrayView get_resolving_list(); - - /** - * Try to resolve a private resolvable address. - * - * @param resolvable_address The address to resolve. - * - * @return Pointer to the entry found if any. - */ - const resolving_list_entry_t* resolve_address( - const address_t& resolvable_address - ); - + ArrayView get_resolving_list(); //////////////////////////////////////////////////////////////////////////// // Pairing @@ -396,7 +369,7 @@ private: static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; size_t resolving_list_entry_count; - resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; + ble_gap_id_key_t resolving_list[MAX_RESOLVING_LIST_ENTRIES]; }; } // nordic From 57a02d6329d3414640d41bfe8499fcc34071aa05 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 16 May 2018 16:54:47 +0100 Subject: [PATCH 234/274] fixed signature --- .../targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h index ca4e069d80..6be90ff733 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGattServer.h @@ -39,7 +39,7 @@ public: /* nRF51 Functions */ void eventCallback(void); - void hwCallback(ble_evt_t *p_ble_evt); + void hwCallback(const ble_evt_t *p_ble_evt); private: From b845a9dc95a5003de073ff7b5ee66f2a7f5ec89f Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 16 May 2018 17:24:17 +0100 Subject: [PATCH 235/274] fixed doxygen --- features/FEATURE_BLE/ble/Gap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index adaf06bc44..052931b801 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -2175,7 +2175,7 @@ public: * resolved and advertisement packets are forwarded to the application * even if the advertiser private address is unknown. * - * @param enable[in] Should be set to true to enable the privacy mode and + * @param[in] enable Should be set to true to enable the privacy mode and * false to disable it. * * @return BLE_ERROR_NONE in case of success or an appropriate error code. From e5d91932fdcf2f5185e1285049d17fa49040f998 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 17 May 2018 10:26:04 +0100 Subject: [PATCH 236/274] BLE: Revert address type changes. The changes made to BLEProtocol::AddressType was not entirelly backward compatible as BLEProtocol::AddressType split random addresses in three category while the type RANDOM is a superset of these types. --- features/FEATURE_BLE/ble/BLEProtocol.h | 20 +------------------- features/FEATURE_BLE/ble/Gap.h | 3 --- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLEProtocol.h b/features/FEATURE_BLE/ble/BLEProtocol.h index 63a61bc1eb..cce3e24c49 100644 --- a/features/FEATURE_BLE/ble/BLEProtocol.h +++ b/features/FEATURE_BLE/ble/BLEProtocol.h @@ -87,25 +87,7 @@ namespace BLEProtocol { * on RANDOM instead. Use Gap::getRandomAddressType to retrieve the * type of the random address. */ - RANDOM_PRIVATE_NON_RESOLVABLE, - - /** - * Random address. - * - * Use Gap::getRandomAddressType to retrieve the type of the random - * address. - */ - RANDOM, - - /** - * A Public address used as a device identity address. - */ - PUBLIC_IDENTITY, - - /** - * A Random static address used as a device identity address. - */ - RANDOM_STATIC_IDENTITY + RANDOM_PRIVATE_NON_RESOLVABLE }; }; diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 052931b801..9818a40141 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -294,9 +294,6 @@ public: */ enum DeprecatedAddressType_t { ADDR_TYPE_PUBLIC = BLEProtocol::AddressType::PUBLIC, - ADDR_TYPE_RANDOM = BLEProtocol::AddressType::RANDOM, - ADDR_TYPE_PUBLIC_IDENTITY = BLEProtocol::AddressType::PUBLIC_IDENTITY, - ADDR_TYPE_RANDOM_STATIC_IDENTITY = BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY, ADDR_TYPE_RANDOM_STATIC = BLEProtocol::AddressType::RANDOM_STATIC, ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE, ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE From 7f05fc0e005e41ffeeac577f9baf9167b8dc2c9c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 17 May 2018 10:30:24 +0100 Subject: [PATCH 237/274] BLE: Define peer_address_type_t This type model a peer address, unlike BLEProtocol::AddressType, it is compatible with privacy concepts. --- features/FEATURE_BLE/ble/BLETypes.h | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index d595299350..5a5b13fb22 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -529,6 +529,43 @@ struct att_security_requirement_t : SafeEnum(value) { } }; +/** + * Type that describes a peer device address type. + */ +struct peer_address_type_t :SafeEnum { + /** struct scoped enum wrapped by the class */ + enum type { + /** + * Public device address. + */ + PUBLIC = 0, + + /** + * Random address. + * + * Use Gap::getRandomAddressType to retrieve the type of the random + * address. + */ + RANDOM, + + /** + * A Public address used as a device identity address. + */ + PUBLIC_IDENTITY, + + /** + * A Random static address used as a device identity address. + */ + RANDOM_STATIC_IDENTITY + }; + + /** + * Construct a new instance of peer_address_type_t. + */ + peer_address_type_t(type value) : + SafeEnum(value) { } +}; + } // namespace ble /** From 0eb680a08bb57ba6189b9a1f1ae4804d9896fd6c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 17 May 2018 10:56:29 +0100 Subject: [PATCH 238/274] GenericGap: Revert changes introduced to accomodate privacy. --- .../FEATURE_BLE/source/generic/GenericGap.cpp | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 12bcd14c48..c05ec5cd64 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -316,7 +316,7 @@ static bool is_whitelist_valid(const Gap::Whitelist_t& whitelist) for (size_t i = 0; i < whitelist.size; ++i) { const BLEProtocol::Address_t& address = whitelist.addresses[i]; if (address.type != BLEProtocol::AddressType::PUBLIC && - address.type != BLEProtocol::AddressType::RANDOM + address.type != BLEProtocol::AddressType::RANDOM_STATIC ) { return false; } @@ -423,7 +423,6 @@ ble_error_t GenericGap::setAddress( _address_type = type; return BLE_ERROR_NONE; - case BLEProtocol::AddressType::RANDOM: case BLEProtocol::AddressType::RANDOM_STATIC: { if (is_random_static_address(address) == false) { return BLE_ERROR_INVALID_PARAM; @@ -436,12 +435,18 @@ ble_error_t GenericGap::setAddress( return err; } - _address_type = BLEProtocol::AddressType::RANDOM; + _address_type = type; _address = ble::address_t(address); _random_static_identity_address = ble::address_t(address); return BLE_ERROR_NONE; } + case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: + case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + // Note: it is not allowed to set directly these addresses + // privacy management handled it for users. + return BLE_ERROR_INVALID_PARAM; + default: return BLE_ERROR_INVALID_PARAM; } @@ -454,17 +459,10 @@ ble_error_t GenericGap::getAddress( *type = _address_type; ble::address_t address_value; - switch (_address_type) { - case BLEProtocol::AddressType::PUBLIC: - address_value = _pal_gap.get_device_address(); - break; - - case BLEProtocol::AddressType::RANDOM: - address_value = _pal_gap.get_random_address(); - break; - - default: - return BLE_ERROR_INVALID_PARAM; + if (_address_type == BLEProtocol::AddressType::PUBLIC) { + address_value = _pal_gap.get_device_address(); + } else { + address_value = _pal_gap.get_random_address(); } memcpy(address, address_value.data(), address_value.size()); @@ -879,10 +877,10 @@ ble_error_t GenericGap::initRadioNotification(void) return BLE_ERROR_NOT_IMPLEMENTED; } -ble_error_t GenericGap::enablePrivacy(bool enable) +ble_error_t GenericGap::enablePrivacy(bool enable) { - if(enable == _privacy_enabled) { - // No change + if(enable == _privacy_enabled) { + // No change return BLE_ERROR_NONE; } @@ -901,7 +899,7 @@ ble_error_t GenericGap::enablePrivacy(bool enable) ble_error_t GenericGap::setPeripheralPrivacyConfiguration( const PeripheralPrivacyConfiguration_t *configuration -) +) { _peripheral_privacy_configuration = *configuration; @@ -912,7 +910,7 @@ ble_error_t GenericGap::setPeripheralPrivacyConfiguration( ble_error_t GenericGap::getPeripheralPrivacyConfiguration( PeripheralPrivacyConfiguration_t *configuration -) +) { *configuration = _peripheral_privacy_configuration; @@ -921,7 +919,7 @@ ble_error_t GenericGap::getPeripheralPrivacyConfiguration( ble_error_t GenericGap::setCentralPrivacyConfiguration( const CentralPrivacyConfiguration_t *configuration -) +) { _central_privacy_configuration = *configuration; @@ -932,7 +930,7 @@ ble_error_t GenericGap::setCentralPrivacyConfiguration( ble_error_t GenericGap::getCentralPrivacyConfiguration( CentralPrivacyConfiguration_t *configuration -) +) { *configuration = _central_privacy_configuration; @@ -962,9 +960,9 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) } // We can only use non resolvable addresses if the device is non connectable - AddressUseType_t address_use_type = + AddressUseType_t address_use_type = ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) - || (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) + || (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ? PERIPHERAL_NON_CONNECTABLE : PERIPHERAL_CONNECTABLE; pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); @@ -1175,7 +1173,7 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e // Apply privacy policy if in peripheral mode for non-resolved addresses RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); ble_error_t ret = getRandomAddressType(e.peer_address.data(), &random_address_type); - if((ret != BLE_ERROR_NONE) + if((ret != BLE_ERROR_NONE) || (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE)) { switch(_peripheral_privacy_configuration.resolution_strategy) @@ -1242,7 +1240,7 @@ void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e // TODO: GAP Authentication != Security Manager authentication // Needs to be implemented } - } else { + } else { // for now notify user that the connection failled by issuing a timeout // event @@ -1369,7 +1367,7 @@ void GenericGap::set_random_address_rotation(bool enable) _random_address_rotating = enable; if(enable) { - // Set first address + // Set first address update_random_address(); // Schedule rotations every 15 minutes as recomended by the spec From a052afdd40c0bdce7dea9795b8ab4186f0d41860 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 17 May 2018 13:27:15 +0100 Subject: [PATCH 239/274] BLE: Update APIs to take advantage of ble::peer_address_type_t Deprecation: * Gap::AdvertisementCallback::addressType has been deprecated in favor of Gap::AdvertisementCallback::peerAddrType. * Gap::ConnectionCallbackParams::peerAddrType has been deprecated in favor of Gap::ConnectionCallbackParams::peerAddressType. * Gap::ConnectionCallbackParams::ownAddr has been deprecated in favor of nothing else as this information may be not available. Overloads added to accept a peer_address_t: * Gap::connect * Gap::processConnectionEvent * Gap::processAdvertisingReport --- features/FEATURE_BLE/ble/BLE.h | 12 +- features/FEATURE_BLE/ble/Gap.h | 284 +++++++++++++++++++------ features/FEATURE_BLE/source/BLE.cpp | 87 ++++++-- features/FEATURE_BLE/source/Gap.cpp | 312 +++++++++++++++++++++++++++- 4 files changed, 595 insertions(+), 100 deletions(-) diff --git a/features/FEATURE_BLE/ble/BLE.h b/features/FEATURE_BLE/ble/BLE.h index 66bb545c3e..d117e5614a 100644 --- a/features/FEATURE_BLE/ble/BLE.h +++ b/features/FEATURE_BLE/ble/BLE.h @@ -457,9 +457,7 @@ public: ble_error_t setAddress( BLEProtocol::AddressType_t type, const BLEProtocol::AddressBytes_t address - ) { - return gap().setAddress(type, address); - } + ); /** * Fetch the Bluetooth Low Energy MAC address and type. @@ -1009,9 +1007,7 @@ public: ble_error_t connect(const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t peerAddrType = BLEProtocol::AddressType::RANDOM_STATIC, const Gap::ConnectionParams_t *connectionParams = NULL, - const GapScanningParams *scanParams = NULL) { - return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams); - } + const GapScanningParams *scanParams = NULL); /** * This call initiates the disconnection procedure, and its completion is @@ -1045,9 +1041,7 @@ public: * connection. */ MBED_DEPRECATED("Use ble.gap().disconnect(...)") - ble_error_t disconnect(Gap::DisconnectionReason_t reason) { - return gap().disconnect(reason); - } + ble_error_t disconnect(Gap::DisconnectionReason_t reason); /** * Returns the current Gap state of the device using a bitmask that diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 9818a40141..c96c2d2266 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -507,6 +507,11 @@ public: */ typedef ble::random_address_type_t RandomAddressType_t; + /** + * Enumeration of peer address types + */ + typedef ble::peer_address_type_t PeerAddressType_t; + /** * Parameters of a BLE connection. */ @@ -590,6 +595,11 @@ public: * startScan(). */ struct AdvertisementCallbackParams_t { + /** + * Default constructor. + */ + AdvertisementCallbackParams_t(); + /** * BLE address of the device that has advertised the packet. */ @@ -623,10 +633,26 @@ public: /** * Type of the address received. * + * @deprecated AddressType_t do not carry enough information to be used + * when privacy is enabled. Use peerAddressType instead. + * * @note This value should be used in the connect function to establish * a connection with the peer that has sent this advertisement packet. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "addressType won't work in connect when privacy is enabled; please" + "use peerAddrType" + ) AddressType_t addressType; + + /** + * Type of the address received. + * + * @note This value should be used in the connect function to establish + * a connection with the peer that has sent this advertisement packet. + */ + PeerAddressType_t peerAddrType; }; /** @@ -658,7 +684,15 @@ public: /** * Type of the address the peer uses. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use peerAddressType instead. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use peerAddressType instead." + ) BLEProtocol::AddressType_t peerAddrType; /** @@ -673,7 +707,18 @@ public: /** * Address of the local device. + * + * @deprecated The local address used for the connection may not be known, + * Therefore this field is not reliable. + * + * @note All bytes of the address are set to 0 if not applicable */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9", + "A Bluetooth controller is not supposed to return the address it used" + "to connect. With privacy enabled the controller address may be unknown" + "to the host. There is no replacement for this deprecation." + ) BLEProtocol::AddressBytes_t ownAddr; /** @@ -695,6 +740,39 @@ public: */ BLEProtocol::AddressBytes_t localResolvableAddr; + /** + * Type of the address the peer uses. + */ + PeerAddressType_t peerAddressType; + + /** + * Construct an instance of ConnectionCallbackParams_t. + * + * @param[in] handleIn Value to assign to handle. + * @param[in] roleIn Value to assign to role. + * @param[in] peerAddrTypeIn Value to assign to peerAddrType. + * @param[in] peerAddrIn Value to assign to peerAddr. + * @param[in] ownAddrTypeIn Value to assign to ownAddrType. + * @param[in] ownAddrIn Value to assign to ownAddr. This may be NULL. + * @param[in] connectionParamsIn Value to assign to connectionParams. + * @param[in] peerResolvableAddrIn Value to assign to peerResolvableAddr. + * @param[in] localResolvableAddrIn Value to assign to localResolvableAddr. + * + * @note Constructor is not meant to be called by user code. + * The BLE API vendor code generates ConnectionCallbackParams_t. + */ + ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + PeerAddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn = NULL, + const uint8_t *localResolvableAddrIn = NULL + ); + /** * Construct an instance of ConnectionCallbackParams_t. * @@ -710,7 +788,16 @@ public: * * @note Constructor is not meant to be called by user code. * The BLE API vendor code generates ConnectionCallbackParams_t. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the constructor that accepts a + * PeerAddressType_t instead. */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the constructor that accepts a PeerAddressType_t instead." + ) ConnectionCallbackParams_t( Handle_t handleIn, Role_t roleIn, @@ -721,26 +808,15 @@ public: const ConnectionParams_t *connectionParamsIn, const uint8_t *peerResolvableAddrIn = NULL, const uint8_t *localResolvableAddrIn = NULL - ) : handle(handleIn), - role(roleIn), - peerAddrType(peerAddrTypeIn), - peerAddr(), - ownAddrType(ownAddrTypeIn), - ownAddr(), - connectionParams(connectionParamsIn), - peerResolvableAddr(), - localResolvableAddr() - { - memcpy(peerAddr, peerAddrIn, ADDR_LEN); - memcpy(ownAddr, ownAddrIn, ADDR_LEN); - if (peerResolvableAddrIn) { - memcpy(peerResolvableAddr, peerResolvableAddrIn, ADDR_LEN); - } + ); - if (localResolvableAddrIn) { - memcpy(localResolvableAddr, localResolvableAddrIn, ADDR_LEN); - } - } + private: + void constructor_helper( + const uint8_t *peerAddrIn, + const uint8_t *ownAddrIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn + ); }; /** @@ -1145,7 +1221,8 @@ public: * emitted to handlers that have been registered with onConnection(). * * @param[in] peerAddr MAC address of the peer. It must be in LSB format. - * @param[in] peerAddrType Address type of the peer. + * @param[in] peerAddrType Address type of the peer. It is usually obtained + * from advertising frames. * @param[in] connectionParams Connection parameters to use. * @param[in] scanParams Scan parameters used to find the peer. * @@ -1153,6 +1230,47 @@ public: * successfully. The connectionCallChain (if set) is invoked upon * a connection event. */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams + ) { + /* Avoid compiler warnings about unused variables. */ + (void)peerAddr; + (void)peerAddrType; + (void)connectionParams; + (void)scanParams; + + /* Requesting action from porter(s): override this API if this capability + is supported. */ + return BLE_ERROR_NOT_IMPLEMENTED; + } + + /** + * Initiate a connection to a peer. + * + * Once the connection is established, a ConnectionCallbackParams_t event is + * emitted to handlers that have been registered with onConnection(). + * + * @param[in] peerAddr MAC address of the peer. It must be in LSB format. + * @param[in] peerAddrType Address type of the peer. + * @param[in] connectionParams Connection parameters to use. + * @param[in] scanParams Scan parameters used to find the peer. + * + * @deprecated BLEProtocol::AddressType_t is not able to to carry accurate + * meaning when privacy is in use. Please Uses the connect overload that + * accept a PeerAddressType_t as the peer address type. + * + * @return BLE_ERROR_NONE if connection establishment procedure is started + * successfully. The connectionCallChain (if set) is invoked upon + * a connection event. + */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "This function won't work if privacy is enabled; You must use the overload " + "accepting PeerAddressType_t." + ) virtual ble_error_t connect( const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t peerAddrType, @@ -1190,15 +1308,7 @@ public: DeprecatedAddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams - ) { - return connect( - peerAddr, - (BLEProtocol::AddressType_t) - peerAddrType, - connectionParams, - scanParams - ); - } + ); /** * Initiate a disconnection procedure. @@ -2563,11 +2673,50 @@ public: * @param[in] peerAddr Address of the connected peer. * @param[in] ownAddrType Address type this device uses for this * connection. - * @param[in] ownAddr Address this device uses for this connection. + * @param[in] ownAddr Address this device uses for this connection. This + * parameter may be NULL if the local address is not available. * @param[in] connectionParams Parameters of the connection. * @param[in] peerResolvableAddr Resolvable address used by the peer. * @param[in] localResolvableAddr resolvable address used by the local device. */ + void processConnectionEvent( + Handle_t handle, + Role_t role, + PeerAddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr = NULL, + const uint8_t *localResolvableAddr = NULL + ); + + /** + * Notify all registered connection event handlers of a connection event. + * + * @attention This function is meant to be called from the BLE stack specific + * implementation when a connection event occurs. + * + * @param[in] handle Handle of the new connection. + * @param[in] role Role of this BLE device in the connection. + * @param[in] peerAddrType Address type of the connected peer. + * @param[in] peerAddr Address of the connected peer. + * @param[in] ownAddrType Address type this device uses for this + * connection. + * @param[in] ownAddr Address this device uses for this connection. + * @param[in] connectionParams Parameters of the connection. + * @param[in] peerResolvableAddr Resolvable address used by the peer. + * @param[in] localResolvableAddr resolvable address used by the local device. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the overload that accepts a PeerAddressType_t + * instead. + */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the overload that accepts a PeerAddressType_t instead." + ) void processConnectionEvent( Handle_t handle, Role_t role, @@ -2578,26 +2727,7 @@ public: const ConnectionParams_t *connectionParams, const uint8_t *peerResolvableAddr = NULL, const uint8_t *localResolvableAddr = NULL - ) { - /* Update Gap state */ - state.advertising = 0; - state.connected = 1; - ++connectionCount; - - ConnectionCallbackParams_t callbackParams( - handle, - role, - peerAddrType, - peerAddr, - ownAddrType, - ownAddr, - connectionParams, - peerResolvableAddr, - localResolvableAddr - ); - - connectionCallChain.call(&callbackParams); - } + ); /** * Notify all registered disconnection event handlers of a disconnection event. @@ -2634,7 +2764,8 @@ public: * @param[in] type Advertising type of the packet. * @param[in] advertisingDataLen Length of the advertisement data received. * @param[in] advertisingData Pointer to the advertisement packet's data. - * @param[in] addressType Type of the address of the peer that has emitted the packet. + * @param[in] addressType Type of the address of the peer that has emitted + * the packet. */ void processAdvertisementReport( const BLEProtocol::AddressBytes_t peerAddr, @@ -2643,22 +2774,43 @@ public: GapAdvertisingParams::AdvertisingType_t type, uint8_t advertisingDataLen, const uint8_t *advertisingData, - BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM - ) { - // FIXME: remove default parameter for addressType when ST shield is merged; - // this has been added to mitigate the lack of dependency management in - // testing jobs .... + PeerAddressType_t addressType + ); - AdvertisementCallbackParams_t params; - memcpy(params.peerAddr, peerAddr, ADDR_LEN); - params.rssi = rssi; - params.isScanResponse = isScanResponse; - params.type = type; - params.advertisingDataLen = advertisingDataLen; - params.advertisingData = advertisingData; - params.addressType = addressType; - onAdvertisementReport.call(¶ms); - } + /** + * Forward a received advertising packet to all registered event handlers + * listening for scanned packet events. + * + * @attention This function is meant to be called from the BLE stack specific + * implementation when a disconnection event occurs. + * + * @param[in] peerAddr Address of the peer that has emitted the packet. + * @param[in] rssi Value of the RSSI measured for the received packet. + * @param[in] isScanResponse If true, then the packet is a response to a scan + * request. + * @param[in] type Advertising type of the packet. + * @param[in] advertisingDataLen Length of the advertisement data received. + * @param[in] advertisingData Pointer to the advertisement packet's data. + * @param[in] addressType Type of the address of the peer that has emitted the packet. + * + * @deprecated The type BLEProtocol::AddressType_t is not suitable when + * privacy is enabled. Use the overload that accepts a PeerAddressType_t + * instead. + */ + MBED_DEPRECATED_SINCE( + "mbed-os-5.9.0", + "The type BLEProtocol::AddressType_t is not suitable when privacy is " + "enabled. Use the overload that accepts a PeerAddressType_t instead." + ) + void processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + BLEProtocol::AddressType_t addressType = BLEProtocol::AddressType::RANDOM_STATIC + ); /** * Notify the occurrence of a timeout event to all registered timeout events diff --git a/features/FEATURE_BLE/source/BLE.cpp b/features/FEATURE_BLE/source/BLE.cpp index 9eba68f96e..a78ec5861a 100644 --- a/features/FEATURE_BLE/source/BLE.cpp +++ b/features/FEATURE_BLE/source/BLE.cpp @@ -31,6 +31,28 @@ #include #endif +#if defined(__GNUC__) && !defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_BEGIN \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_BEGIN \ + _Pragma("push") \ + _Pragma("diag_suppress 1361") +#else +#define BLE_DEPRECATED_API_USE_BEGIN +#endif + +#if defined(__GNUC__) && !defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_END \ + _Pragma("GCC diagnostic pop") +#elif defined(__CC_ARM) +#define BLE_DEPRECATED_API_USE_END \ + _Pragma("pop") +#else +#define BLE_DEPRECATED_API_USE_BEGIN +#endif + static const char* error_strings[] = { "BLE_ERROR_NONE: No error", "BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted", @@ -143,14 +165,18 @@ BLE::Instance(InstanceID_t id) static BLE *singletons[NUM_INSTANCES]; if (id < NUM_INSTANCES) { if (singletons[id] == NULL) { +BLE_DEPRECATED_API_USE_BEGIN singletons[id] = new BLE(id); /* This object will never be freed. */ +BLE_DEPRECATED_API_USE_END } return *singletons[id]; } /* we come here only in the case of a bad interfaceID. */ +BLE_DEPRECATED_API_USE_BEGIN static BLE badSingleton(NUM_INSTANCES /* this is a bad index; and will result in a NULL transport. */); +BLE_DEPRECATED_API_USE_END return badSingleton; } @@ -162,23 +188,6 @@ void defaultSchedulingCallback(BLE::OnEventsToProcessCallbackContext* params) { #define defaultSchedulingCallback NULL #endif - -BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(), - whenEventsToProcess(defaultSchedulingCallback), - event_signaled(false) -{ - static BLEInstanceBase *transportInstances[NUM_INSTANCES]; - - if (instanceID < NUM_INSTANCES) { - if (!transportInstances[instanceID]) { - transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */ - } - transport = transportInstances[instanceID]; - } else { - transport = NULL; - } -} - bool BLE::hasInitialized(void) const { if (!transport) { @@ -332,3 +341,47 @@ void BLE::signalEventsToProcess() whenEventsToProcess(¶ms); } } + +// start of deprecated functions + +BLE_DEPRECATED_API_USE_BEGIN + +// NOTE: move and remove deprecation once private +BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport(), + whenEventsToProcess(defaultSchedulingCallback), + event_signaled(false) +{ + static BLEInstanceBase *transportInstances[NUM_INSTANCES]; + + if (instanceID < NUM_INSTANCES) { + if (!transportInstances[instanceID]) { + transportInstances[instanceID] = instanceConstructors[instanceID](); /* Call the stack's initializer for the transport object. */ + } + transport = transportInstances[instanceID]; + } else { + transport = NULL; + } +} + +ble_error_t BLE::setAddress( + BLEProtocol::AddressType_t type, + const BLEProtocol::AddressBytes_t address +) { + return gap().setAddress(type, address); +} + +ble_error_t BLE::connect( + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t peerAddrType, + const Gap::ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams +) { + return gap().connect(peerAddr, peerAddrType, connectionParams, scanParams); +} + +ble_error_t BLE::disconnect(Gap::DisconnectionReason_t reason) { + return gap().disconnect(reason); +} + +BLE_DEPRECATED_API_USE_END + diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index 425f833106..ca39bb645d 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -16,6 +16,152 @@ #include "ble/Gap.h" +namespace { + +ble_error_t convert_address_type( + Gap::PeerAddressType_t input_type, + const BLEProtocol::AddressBytes_t address, + BLEProtocol::AddressType_t& output_type +) { + typedef Gap::RandomAddressType_t RandomAddressType_t; + typedef Gap::PeerAddressType_t PeerAddressType_t; + typedef BLEProtocol::AddressType LegacyAddressType_t; + + // best effort; peerAddrTypeIn should not be used when privacy is on. + switch(input_type.value()) { + case PeerAddressType_t::PUBLIC: + case PeerAddressType_t::PUBLIC_IDENTITY: + output_type = LegacyAddressType_t::PUBLIC; + break; + case PeerAddressType_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = Gap::getRandomAddressType(address, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + output_type = LegacyAddressType_t::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + output_type = LegacyAddressType_t::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + output_type = LegacyAddressType_t::RANDOM_PRIVATE_RESOLVABLE; + break; + } + break; + } + case PeerAddressType_t::RANDOM_STATIC_IDENTITY: + output_type = LegacyAddressType_t::RANDOM_STATIC; + break; + } + + return BLE_ERROR_NONE; +} + +Gap::PeerAddressType_t convert_legacy_address_type( + BLEProtocol::AddressType_t legacy_address +) { + if (legacy_address == BLEProtocol::AddressType::PUBLIC) { + return Gap::PeerAddressType_t::PUBLIC; + } else { + return Gap::PeerAddressType_t::RANDOM; + } +} + +} + +const Gap::PeripheralPrivacyConfiguration_t Gap::default_peripheral_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE +}; + +const Gap::CentralPrivacyConfiguration_t Gap::default_central_privacy_configuration = { + /* use_non_resolvable_random_address */ false, + /* resolution_strategy */ CentralPrivacyConfiguration_t::DO_NOT_RESOLVE +}; + +void Gap::processConnectionEvent( + Handle_t handle, + Role_t role, + PeerAddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr +) { + /* Update Gap state */ + state.advertising = 0; + state.connected = 1; + ++connectionCount; + + ConnectionCallbackParams_t callbackParams( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams, + peerResolvableAddr, + localResolvableAddr + ); + + connectionCallChain.call(&callbackParams); +} + +void Gap::processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + PeerAddressType_t addressType +) { + AdvertisementCallbackParams_t params; + + memcpy(params.peerAddr, peerAddr, ADDR_LEN); + params.rssi = rssi; + params.isScanResponse = isScanResponse; + params.type = type; + params.advertisingDataLen = advertisingDataLen; + params.advertisingData = advertisingData; + params.peerAddrType = addressType; + + convert_address_type( + addressType, + peerAddr, + params.addressType + ); + + onAdvertisementReport.call(¶ms); +} + + +#if defined(__GNUC__) && !defined(__CC_ARM) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#elif defined(__CC_ARM) +#pragma push +#pragma diag_suppress 1361 +#endif + +Gap::AdvertisementCallbackParams_t::AdvertisementCallbackParams_t() : + peerAddr(), + rssi(), + isScanResponse(), + type(), + advertisingDataLen(0), + advertisingData(NULL), + addressType(), + peerAddrType(PeerAddressType_t::PUBLIC) +{ +} + ble_error_t Gap::getRandomAddressType( const BLEProtocol::AddressBytes_t address, RandomAddressType_t* type @@ -37,12 +183,162 @@ ble_error_t Gap::getRandomAddressType( } } -const Gap::PeripheralPrivacyConfiguration_t Gap::default_peripheral_privacy_configuration = { - /* use_non_resolvable_random_address */ false, - /* resolution_strategy */ PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE -}; +Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + BLEProtocol::AddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) : handle(handleIn), + role(roleIn), + peerAddrType(peerAddrTypeIn), + peerAddr(), + ownAddrType(ownAddrTypeIn), + ownAddr(), + connectionParams(connectionParamsIn), + peerResolvableAddr(), + localResolvableAddr(), + peerAddressType(convert_legacy_address_type(peerAddrTypeIn)) +{ + constructor_helper( + peerAddrIn, + ownAddrIn, + peerResolvableAddrIn, + localResolvableAddrIn + ); +} -const Gap::CentralPrivacyConfiguration_t Gap::default_central_privacy_configuration = { - /* use_non_resolvable_random_address */ false, - /* resolution_strategy */ CentralPrivacyConfiguration_t::DO_NOT_RESOLVE -}; +Gap::ConnectionCallbackParams_t::ConnectionCallbackParams_t( + Handle_t handleIn, + Role_t roleIn, + PeerAddressType_t peerAddrTypeIn, + const uint8_t *peerAddrIn, + BLEProtocol::AddressType_t ownAddrTypeIn, + const uint8_t *ownAddrIn, + const ConnectionParams_t *connectionParamsIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) : handle(handleIn), + role(roleIn), + peerAddrType(), + peerAddr(), + ownAddrType(ownAddrTypeIn), + ownAddr(), + connectionParams(connectionParamsIn), + peerResolvableAddr(), + localResolvableAddr(), + peerAddressType(peerAddrTypeIn) +{ + constructor_helper( + peerAddrIn, + ownAddrIn, + peerResolvableAddrIn, + localResolvableAddrIn + ); + + convert_address_type(peerAddrTypeIn, peerAddrIn, peerAddrType); +} + +void Gap::ConnectionCallbackParams_t::constructor_helper( + const uint8_t *peerAddrIn, + const uint8_t *ownAddrIn, + const uint8_t *peerResolvableAddrIn, + const uint8_t *localResolvableAddrIn +) { + memcpy(peerAddr, peerAddrIn, ADDR_LEN); + + if (ownAddrIn) { + memcpy(ownAddr, ownAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } + + if (peerResolvableAddrIn) { + memcpy(peerResolvableAddr, peerResolvableAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } + + if (localResolvableAddrIn) { + memcpy(localResolvableAddr, localResolvableAddrIn, ADDR_LEN); + } else { + memset(ownAddr, 0, ADDR_LEN); + } +} + +ble_error_t Gap::connect( + const BLEProtocol::AddressBytes_t peerAddr, + DeprecatedAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams +) { + return connect( + peerAddr, + (BLEProtocol::AddressType_t) peerAddrType, + connectionParams, + scanParams + ); +} + +void Gap::processConnectionEvent( + Handle_t handle, + Role_t role, + BLEProtocol::AddressType_t peerAddrType, + const BLEProtocol::AddressBytes_t peerAddr, + BLEProtocol::AddressType_t ownAddrType, + const BLEProtocol::AddressBytes_t ownAddr, + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr +) { + /* Update Gap state */ + state.advertising = 0; + state.connected = 1; + ++connectionCount; + + ConnectionCallbackParams_t callbackParams( + handle, + role, + peerAddrType, + peerAddr, + ownAddrType, + ownAddr, + connectionParams, + peerResolvableAddr, + localResolvableAddr + ); + + connectionCallChain.call(&callbackParams); +} + +void Gap::processAdvertisementReport( + const BLEProtocol::AddressBytes_t peerAddr, + int8_t rssi, + bool isScanResponse, + GapAdvertisingParams::AdvertisingType_t type, + uint8_t advertisingDataLen, + const uint8_t *advertisingData, + BLEProtocol::AddressType_t addressType +) { + AdvertisementCallbackParams_t params; + memcpy(params.peerAddr, peerAddr, ADDR_LEN); + params.rssi = rssi; + params.isScanResponse = isScanResponse; + params.type = type; + params.advertisingDataLen = advertisingDataLen; + params.advertisingData = advertisingData; + params.addressType = addressType; + + params.peerAddrType = convert_legacy_address_type(addressType); + onAdvertisementReport.call(¶ms); +} + +#if defined(__GNUC__) && !defined(__CC_ARM) +#pragma GCC diagnostic pop +#elif defined(__CC_ARM) +#pragma pop +#endif From 7e694444588452f219db8a91966a6d658700724a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 17 May 2018 14:10:57 +0100 Subject: [PATCH 240/274] security manager doxygen overview updated --- features/FEATURE_BLE/ble/SecurityManager.h | 36 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 80b34705c1..c99ebd702a 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -31,7 +31,9 @@ * and/or exchanging keys used for the current connection. Bonding means saving this information so that * it can later be used after reconnecting without having to pair again. This saves time and power. * - * There are many ways to provide these at different levels of security depending on your requirements + * @par Paring + * + * There are several ways to provide different levels of security during pairing depending on your requirements * and the facilities provided by the application. The process starts with initialising the SecurityManager * with default options for new connections. Some settings can later be changed per link or globally. * @@ -43,6 +45,8 @@ * You can change the IO capabilities after initialisation with setIoCapability(). This will take effect * for all subsequent pairings. * + * @par Out of Band data used in pairing + * * Sharing this information through IO capabilities means user interaction which limits the degree of * protection due to the limit of the amount of data that we can expect the user to transfer. Another * solution is using OOB (out of band) communication to transfer this data instead which can send much @@ -57,7 +61,27 @@ * it. If either side doesn't support it Legacy Pairing will be used. This is an older standard of pairing. * If higher security is required legacy pairing can be disabled by calling allowLegacyPairing(false); * - * \par How to use + * @par Signing + * + * Applications may require a level of security providing confidence that data transfers are coming + * from a trusted source. This can be achieved by encrypting the link which also provides added confidentiality. + * Encryption is a good choice when a device stays connected but introduces latency due to the need of encrypting the + * link if the device only connects periodically to transfer data. If confidentiality is not required data GATT + * server may allow writes to happen over an unencrypted link but authenticated by a signature present in each packet. + * This signature relies on having sent a signing key to the peer during pairing prior to sending any signed packets. + * + * @par Persistence of Security information + * + * Security Manager stores all the data required for its operation on active links. Depending on resources + * available on the device it will also attempt to store data for disconnected devices which have bonded to be + * reused when reconnected. + * + * If the application has initialised a filesystem and the Security Manager has been provided with a + * filepath during the init() call it may also provide data persistence across resets. This must be enabled by + * calling preserveBondingStateOnReset(). Persistence is not guaranteed and may fail if abnormally terminated. + * The Security Manager may also fall back to a non-persistent implementation if the resources are too limited. + * + * @par How to use * * First thing you need to do is to initialise the manager by calling init() with your chosen settings. * @@ -87,7 +111,7 @@ * accetPairing() or cancelPairing(). The result will be communicated on both peers through an event calling * pairingResult() in the EventHandler. * - * \par Sequence diagrams + * @par Sequence diagrams * * Sequence diagram "Just Works" pairing * @@ -103,7 +127,7 @@ * | | |<---[pairing complete]----->| | | * |<- pairingResult() <---------------| |----------------> pairingResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * * @note the requestPairing() call isn't required to trigger pairing. Pairing will also be triggered * if you request encryption and authentication and no bonding information is available. The sequence will @@ -121,7 +145,7 @@ * | | |<-[encryption established]->| | | * |<- linkEncryptionResult() <--------| |---------> linkEncryptionResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * * @note if bonding information is not available, pairing will be triggered * @@ -149,7 +173,7 @@ * | | |<---[pairing complete]----->| | | * |<- pairingResult() <---------------| |----------------> pairingResult() -->| * | | | | | | - * \endverbatim + * @endverbatim * */ From a8ac925b4f0781937a99bb4258fa8f806dc4aed4 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Thu, 17 May 2018 16:48:49 +0100 Subject: [PATCH 241/274] privacy doxygen overview --- features/FEATURE_BLE/ble/Gap.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/features/FEATURE_BLE/ble/Gap.h b/features/FEATURE_BLE/ble/Gap.h index 052931b801..bb4f264cf3 100644 --- a/features/FEATURE_BLE/ble/Gap.h +++ b/features/FEATURE_BLE/ble/Gap.h @@ -121,6 +121,27 @@ class GapAdvertisingData; * gap.startAdvertising(); * @endcode * + * @par Privacy + * + * Privacy is a feature that allows a device to avoid being tracked by other + * (untrusted) devices. The device achieves it by periodically generating a + * new random address. The random address may be a resolvable random address, + * enabling trusted devices to recognise it as belonging to the same + * device. These trusted devices receive an Identity Resolution Key (IRK) + * during pairing. This is handled by the SecurityManager and relies on the + * other device accepting and storing the IRK. + * + * Privacy needs to be enabled by calling enablePrivacy() after having + * initialised the SecurityManager since privacy requires SecurityManager + * to handle IRKs. The behaviour of privacy enabled devices is set by + * using setCentralPrivacyConfiguration() which specifies what the device + * should be with devices using random addresses. Random addresses + * generated by privacy enabled device can be of two types: resolvable + * (by devices who have the IRK) and unresolvable. Unresolvable addresses + * can't be used for connecting and connectable advertising therefore a + * resolvable one will be used for these regardless of the privacy + * configuration. + * * @par Scanning * * Scanning consist of listening for peer advertising packets. From a scan, a From d361960aa35a98d4d11fb401c2c23ae8b62a5ed3 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 18 May 2018 10:04:27 +0100 Subject: [PATCH 242/274] BLE: Use peer_address_type_t instead of the legacy address in security manager. --- .../ble/generic/GenericSecurityManager.h | 5 +++-- features/FEATURE_BLE/ble/generic/SecurityDb.h | 16 ++++++++-------- .../FEATURE_BLE/ble/pal/ConnectionEventMonitor.h | 7 +++++-- .../source/generic/GenericSecurityManager.cpp | 14 +++++++++++--- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index f5f060a5e6..b2c74248bc 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -381,11 +381,12 @@ private: virtual void on_connected( connection_handle_t connection, Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const Gap::ConnectionParams_t *connection_params + const Gap::ConnectionParams_t *connection_params, + const BLEProtocol::AddressBytes_t resolved_peer_address ); /** diff --git a/features/FEATURE_BLE/ble/generic/SecurityDb.h b/features/FEATURE_BLE/ble/generic/SecurityDb.h index 009d769554..b8c2ea25c8 100644 --- a/features/FEATURE_BLE/ble/generic/SecurityDb.h +++ b/features/FEATURE_BLE/ble/generic/SecurityDb.h @@ -440,7 +440,7 @@ public: * @return A handle to the entry. */ virtual entry_handle_t open_entry( - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const address_t &peer_address ) { entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); @@ -451,8 +451,8 @@ public: 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); + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::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 */ @@ -473,12 +473,12 @@ public: * @return A handle to the entry. */ virtual entry_handle_t find_entry_by_peer_address( - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_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); + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY); for (size_t i = 0; i < get_entry_count(); i++) { entry_handle_t db_handle = get_entry_handle_by_index(i); @@ -486,7 +486,7 @@ public: /* only look among disconnected entries */ if (flags && !flags->connected) { - if (peer_address_type == BLEProtocol::AddressType::PUBLIC_IDENTITY && + if (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY && flags->irk_stored == false) { continue; } @@ -536,7 +536,7 @@ public: * @return A handle to the entry. */ virtual void remove_entry( - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const address_t &peer_address ) { entry_handle_t db_handle = find_entry_by_peer_address(peer_address_type, peer_address); diff --git a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h index d0a0325bde..0695bf1197 100644 --- a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h +++ b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h @@ -48,15 +48,18 @@ public: * @param[in] local_address_type type of address of the local device. * @param[in] local_address Address of the local device that was used during connection. * @param[in] connection_params connection parameters like interval, latency and timeout. + * @param[in] resolved_peer_address resolved address of the peer; may + * be NULL. */ virtual void on_connected( connection_handle_t connection, ::Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + ble::peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const ::Gap::ConnectionParams_t *connection_params + const ::Gap::ConnectionParams_t *connection_params, + const BLEProtocol::AddressBytes_t resolved_peer_address ) = 0; /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index bb03c2f548..9fef7c4cc8 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -964,11 +964,12 @@ void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, void GenericSecurityManager::on_connected( connection_handle_t connection, Gap::Role_t role, - BLEProtocol::AddressType_t peer_address_type, + peer_address_type_t peer_address_type, const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const Gap::ConnectionParams_t *connection_params + const Gap::ConnectionParams_t *connection_params, + const BLEProtocol::AddressBytes_t resolved_peer_address ) { MBED_ASSERT(_db); ControlBlock_t *cb = acquire_control_block(connection); @@ -980,13 +981,20 @@ void GenericSecurityManager::on_connected( cb->local_address = local_address; cb->is_master = (role == Gap::CENTRAL); + // normalize the address + if (resolved_peer_address && resolved_peer_address != ble::address_t()) { + peer_address = resolved_peer_address; + } + // get the associated db handle and the distribution flags if any cb->db_entry = _db->open_entry(peer_address_type, peer_address); SecurityDistributionFlags_t* flags = _db->get_distribution_flags(cb->db_entry); flags->peer_address = peer_address; - flags->peer_address_is_public = (peer_address_type == BLEProtocol::AddressType::PUBLIC); + flags->peer_address_is_public = + (peer_address_type == peer_address_type_t::PUBLIC) || + (peer_address_type == peer_address_type_t::PUBLIC_IDENTITY); const bool signing = cb->signing_override_default ? cb->signing_requested : From c3bcd10cfd1262b39282683a901f27e74b159448 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 18 May 2018 10:09:07 +0100 Subject: [PATCH 243/274] BLE NRF52: Implement features related to peer_address_t The overload of Gap::connect that accept peer_address_t has been added and gap connection and advertising report process have been updated to exploit peer_address_t in a backward compatible fashion. --- .../TARGET_NRF52/source/nRF5xGap.cpp | 223 +++++++++++------- .../TARGET_NRF52/source/nRF5xGap.h | 1 + 2 files changed, 144 insertions(+), 80 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 9b85b6d6ae..aa6884cb85 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -26,10 +26,15 @@ #include "headers/ble_hci.h" #include "ble/pal/ConnectionEventMonitor.h" #include "nRF5xPalSecurityManager.h" +#include using ble::pal::vendor::nordic::nRF5xSecurityManager; using ble::ArrayView; using ble::pal::advertising_peer_address_type_t; +using ble::peer_address_type_t; + +typedef BLEProtocol::AddressType LegacyAddressType; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; namespace { @@ -85,29 +90,32 @@ bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { } } -bool is_identity_address(BLEProtocol::AddressType_t address_type) { - switch (address_type) { - case BLEProtocol::AddressType::PUBLIC_IDENTITY: - case BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY: - return true; - default: - return false; - } +bool is_identity_address(peer_address_type_t address_type) { + return address_type == peer_address_type_t::PUBLIC_IDENTITY || + address_type == peer_address_type_t::RANDOM_STATIC_IDENTITY; } -BLEProtocol::AddressType_t convert_nordic_address(uint8_t address) { - if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { - return BLEProtocol::AddressType::PUBLIC; +peer_address_type_t convert_nordic_address(bool identity, uint8_t address) { + if (identity) { + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return peer_address_type_t::PUBLIC_IDENTITY; + } else { + return peer_address_type_t::RANDOM_STATIC_IDENTITY; + } } else { - return BLEProtocol::AddressType::RANDOM; + if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { + return peer_address_type_t::PUBLIC; + } else { + return peer_address_type_t::RANDOM; + } } } -BLEProtocol::AddressType_t convert_identity_address(advertising_peer_address_type_t address) { +peer_address_type_t convert_identity_address(advertising_peer_address_type_t address) { if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { - return BLEProtocol::AddressType::PUBLIC_IDENTITY; + return peer_address_type_t::PUBLIC_IDENTITY; } else { - return BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY; + return peer_address_type_t::RANDOM_STATIC_IDENTITY; } } @@ -129,7 +137,7 @@ nRF5xGap::nRF5xGap() : Gap(), _privacy_enabled(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), - _non_private_address_type(BLEProtocol::AddressType::RANDOM) + _non_private_address_type(LegacyAddressType::RANDOM_STATIC) { m_connectionHandle = BLE_CONN_HANDLE_INVALID; } @@ -453,11 +461,60 @@ ble_error_t nRF5xGap::stopAdvertising(void) return BLE_ERROR_NONE; } -ble_error_t nRF5xGap::connect(const Address_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t *connectionParams, - const GapScanningParams *scanParamsIn) -{ +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + peer_address_type_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + // NOTE: Nordic address type is an closer to LegacyAddressType: resolved + // address are treaded either as PUBLIC or RANDOM STATIC adresses. + // The idea is to get the conversion done here and call the legacy function. + + LegacyAddressType_t legacy_address; + + switch (peerAddrType.value()) { + case peer_address_type_t::PUBLIC: + case peer_address_type_t::PUBLIC_IDENTITY: + legacy_address = LegacyAddressType::PUBLIC; + break; + case peer_address_type_t::RANDOM_STATIC_IDENTITY: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case peer_address_type_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = getRandomAddressType(peerAddr, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + break; + default: + return BLE_ERROR_UNSPECIFIED; + } + } break; + default: + return BLE_ERROR_INVALID_PARAM; + } + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn); +} + + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { ble_gap_addr_t addr; ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; @@ -722,11 +779,11 @@ uint16_t nRF5xGap::getConnectionHandle(void) @endcode */ /**************************************************************************/ -ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) +ble_error_t nRF5xGap::setAddress(LegacyAddressType_t type, const Address_t address) { - using BLEProtocol::AddressType; - - if (type != AddressType::PUBLIC || type != AddressType::RANDOM_STATIC) { + if (type != LegacyAddressType::PUBLIC && + type != LegacyAddressType::RANDOM_STATIC + ) { return BLE_ERROR_INVALID_PARAM; } @@ -736,7 +793,7 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) ble_gap_addr_t dev_addr; memcpy(dev_addr.addr, address, ADDR_LEN); - if (type == AddressType::PUBLIC) { + if (type == LegacyAddressType::PUBLIC) { dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; } else { dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; @@ -752,8 +809,9 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) case NRF_SUCCESS: return BLE_ERROR_NONE; case NRF_ERROR_INVALID_ADDR: - case BLE_ERROR_GAP_INVALID_BLE_ADDR: return BLE_ERROR_INVALID_PARAM; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_PARAM_OUT_OF_RANGE; case NRF_ERROR_BUSY: return BLE_STACK_BUSY; case NRF_ERROR_INVALID_STATE: @@ -781,11 +839,11 @@ ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) switch (dev_addr.addr_type) { case BLE_GAP_ADDR_TYPE_PUBLIC: - *typeP = BLEProtocol::AddressType::PUBLIC; + *typeP = LegacyAddressType::PUBLIC; break; case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: - *typeP = BLEProtocol::AddressType::RANDOM_STATIC; + *typeP = LegacyAddressType::RANDOM_STATIC; break; default: @@ -924,7 +982,7 @@ ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const uint32_t i; for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { memcpy( &whitelistOut.addresses[i].address, &whitelistAddresses[i].addr, sizeof(whitelistOut.addresses[0].address)); - whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); + whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); } @@ -971,7 +1029,9 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) /* Test for invalid parameters before we change the internal state */ for (uint32_t i = 0; i < whitelistIn.size; ++i) { - if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE || + whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE + ) { /* This is not allowed because it is completely meaningless */ return BLE_ERROR_INVALID_PARAM; } @@ -1260,15 +1320,13 @@ ble_error_t nRF5xGap::update_identities_list(bool resolution_enabled) } void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) { - using BLEProtocol::AddressType; - // set the new connection handle as the _default_ handle in gap setConnectionHandle(handle); // deal with own address - AddressType_t own_addr_type; - Address_t own_address; - const uint8_t* own_resolvable_address = NULL; + LegacyAddressType_t own_addr_type; + ble::address_t own_address; + ble::address_t own_resolvable_address; #if (NRF_SD_BLE_API_VERSION <= 2) if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { @@ -1278,12 +1336,36 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t } memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); #else - // FIXME: handle privacy ??? - getAddress(&own_addr_type, own_address); + getAddress(&own_addr_type, own_address.data()); #endif if (_privacy_enabled) { - own_resolvable_address = own_address; + // swap own address with own resolvable address as when privacy is + // enabled own_address is invalid and the address returned by getAddress + // is the resolvable one. + std::swap(own_address, own_resolvable_address); + own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + } + +#if (NRF_SD_BLE_API_VERSION <= 2) + bool private_peer_known = evt.irk_match; +#else + bool private_peer_known = evt.peer_addr.addr_id_peer; +#endif + + // Filter out private address non resolved if the its required by the + // resolution policy + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + private_peer_known == false && + get_sm().get_resolving_list().size() > 0 + ) { + // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible + // with the softdevice ... + sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + return; } // deal with the peer address: If privacy is enabled then the softdevice @@ -1292,38 +1374,15 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t // Depending on the privacy chosen by the application, connection request // from privacy enabled peers may trigger a disconnection, the pairing procedure // or the authentication procedure. - AddressType_t peer_addr_type; - const uint8_t* peer_address; - const uint8_t* peer_resolvable_address; - -#if (NRF_SD_BLE_API_VERSION <= 2) - bool private_peer_known = evt.irk_match; -#else - bool private_peer_known = evt.peer_addr.addr_id_peer; -#endif - - - if (private_peer_known) { - peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);; - peer_address = evt.peer_addr.addr; - peer_resolvable_address = evt.peer_addr.addr; - } else { - if (_privacy_enabled && - evt.role == BLE_GAP_ROLE_PERIPH && - _peripheral_privacy_configuration.resolution_strategy == PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS && - evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && - get_sm().get_resolving_list().size() > 0 - ) { - // FIXME: should use BLE_HCI_AUTHENTICATION_FAILURE; not possible - // with the softdevice ... - sd_ble_gap_disconnect(handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - return; - } - - peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); - peer_address = evt.peer_addr.addr; - peer_resolvable_address = NULL; - } + peer_address_type_t peer_addr_type = convert_nordic_address( + private_peer_known, + evt.peer_addr.addr_type + ); + // NOTE: when privacy is enabled, the only address returned is the resolved + // address; set peer and resolved address to the same value in such case. + const uint8_t* peer_address = evt.peer_addr.addr; + const uint8_t* peer_resolvable_address = + private_peer_known ? peer_address : NULL; // notify internal event handler before applying the resolution strategy if (_connection_event_handler) { @@ -1333,14 +1392,15 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t peer_addr_type, peer_address, own_addr_type, - own_address, - reinterpret_cast(&(evt.conn_params)) + own_address.data(), + reinterpret_cast(&(evt.conn_params)), + peer_resolvable_address ); } // Apply authentication strategy before application notification - if (!private_peer_known && - _privacy_enabled && + if (_privacy_enabled && + !private_peer_known && evt.role == BLE_GAP_ROLE_PERIPH && evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE ) { @@ -1364,24 +1424,27 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t peer_addr_type, peer_address, own_addr_type, - own_address, + own_address.data(), reinterpret_cast(&(evt.conn_params)), peer_resolvable_address, - own_resolvable_address + own_resolvable_address.data() ); } void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { - using BLEProtocol::AddressType; + bool peer_address_resolved = evt.peer_addr.addr_id_peer; if (_privacy_enabled && - evt.peer_addr.addr_id_peer == 0 && + peer_address_resolved == false && _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER ) { return; } - AddressType_t peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); + peer_address_type_t peer_addr_type = convert_nordic_address( + evt.peer_addr.addr_id_peer, + evt.peer_addr.addr_type + ); const uint8_t* peer_address = evt.peer_addr.addr; processAdvertisementReport( diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index d019d99cdc..27cabc9981 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -86,6 +86,7 @@ public: virtual ble_error_t startAdvertising(const GapAdvertisingParams &); virtual ble_error_t stopAdvertising(void); + virtual ble_error_t connect(const Address_t, ble::peer_address_type_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); From 608ad338e87bdbd1e931b59f82cbfff9d5672767 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 18 May 2018 10:24:16 +0100 Subject: [PATCH 244/274] return error when not initialised --- .../source/generic/GenericSecurityManager.cpp | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index bb03c2f548..9f2f527b0e 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -123,7 +123,7 @@ ble_error_t GenericSecurityManager::reset(void) { } ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _db->set_restore(enabled); return BLE_ERROR_NONE; } @@ -133,13 +133,13 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) { // ble_error_t GenericSecurityManager::purgeAllBondingState(void) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _db->clear_entries(); return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (eventHandler) { _db->generate_whitelist_from_bond_table( mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable), @@ -154,6 +154,7 @@ ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelis // ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -206,6 +207,7 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio } ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -263,10 +265,12 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con } ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON); } ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _pairing_authorisation_required = required; return BLE_ERROR_NONE; } @@ -289,10 +293,12 @@ ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) { // ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_io_capability((io_capability_t::type) iocaps); } ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_display_passkey(PasskeyAscii::to_num(passkey)); } @@ -300,6 +306,7 @@ ble_error_t GenericSecurityManager::setAuthenticationTimeout( connection_handle_t connection, uint32_t timeout_in_ms ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_authentication_timeout(connection, timeout_in_ms / 10); } @@ -307,6 +314,7 @@ ble_error_t GenericSecurityManager::getAuthenticationTimeout( connection_handle_t connection, uint32_t *timeout_in_ms ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; uint16_t timeout_in_10ms; ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms); *timeout_in_ms = 10 * timeout_in_10ms; @@ -317,6 +325,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity( connection_handle_t connection, SecurityMode_t securityMode ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -348,6 +357,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity( } ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; _default_authentication.set_keypress_notification(enabled); return BLE_ERROR_NONE; } @@ -356,7 +366,7 @@ ble_error_t GenericSecurityManager::enableSigning( connection_handle_t connection, bool enabled ) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -406,7 +416,7 @@ ble_error_t GenericSecurityManager::getLinkEncryption( connection_handle_t connection, link_encryption_t *encryption ) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -440,7 +450,7 @@ ble_error_t GenericSecurityManager::setLinkEncryption( connection_handle_t connection, link_encryption_t encryption ) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -511,7 +521,7 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize( connection_handle_t connection, uint8_t *size ) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -530,6 +540,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( uint8_t minimumByteSize, uint8_t maximumByteSize ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize); } @@ -538,7 +549,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements( // ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -576,6 +587,7 @@ ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection // ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.set_private_address_timeout(timeout_in_seconds); } @@ -584,7 +596,7 @@ ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in // ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -619,6 +631,7 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co ble_error_t GenericSecurityManager::generateOOB( const address_t *address ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; /* legacy pairing */ ble_error_t status = get_random_data(_oob_temporary_key.data(), 16); @@ -658,6 +671,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage( bool useOOB, bool OOBProvidesMITM ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -677,6 +691,7 @@ ble_error_t GenericSecurityManager::confirmationEntered( connection_handle_t connection, bool confirmation ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.confirmation_entered(connection, confirmation); } @@ -684,6 +699,7 @@ ble_error_t GenericSecurityManager::passkeyEntered( connection_handle_t connection, Passkey_t passkey ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.passkey_request_reply( connection, PasskeyAscii::to_num(passkey) @@ -694,6 +710,7 @@ ble_error_t GenericSecurityManager::sendKeypressNotification( connection_handle_t connection, Keypress_t keypress ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; return _pal.send_keypress_notification(connection, keypress); } @@ -701,7 +718,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived( const address_t *address, const oob_tk_t *tk ) { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (address && tk) { ControlBlock_t *cb = get_control_block(*address); if (!cb) { @@ -736,6 +753,7 @@ ble_error_t GenericSecurityManager::oobReceived( const oob_lesc_value_t *random, const oob_confirm_t *confirm ) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; if (address && random && confirm) { _oob_peer_address = *address; _oob_peer_random = *random; @@ -751,7 +769,7 @@ ble_error_t GenericSecurityManager::oobReceived( // ble_error_t GenericSecurityManager::init_signing() { - MBED_ASSERT(_db); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; const csrk_t *pcsrk = _db->get_local_csrk(); sign_count_t local_sign_counter = _db->get_local_sign_counter(); @@ -791,6 +809,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size } ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; @@ -801,7 +820,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); + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; ControlBlock_t *cb = get_control_block(connection); if (!cb) { return BLE_ERROR_INVALID_PARAM; From 439d002f7df62e8f597ca50e9c0a52b7761a52eb Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 18 May 2018 12:34:52 +0100 Subject: [PATCH 245/274] new API call to change db at runtime --- features/FEATURE_BLE/ble/SecurityManager.h | 20 ++++++-- .../ble/generic/GenericSecurityManager.h | 2 + .../source/generic/GenericSecurityManager.cpp | 49 ++++++++++++------- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index c99ebd702a..548805c191 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -441,7 +441,7 @@ 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, + * @param[in] dbPath Path to the file used to store keys in the filesystem, * if NULL keys will be only stored in memory * * @@ -452,17 +452,31 @@ public: SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, const Passkey_t passkey = NULL, bool signing = true, - const char *dbPath = NULL) { + const char *dbFilepath = NULL) { /* Avoid compiler warnings about unused variables. */ (void)enableBonding; (void)requireMITM; (void)iocaps; (void)passkey; - (void)dbPath; + (void)dbFilepath; return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ } + /** + * Change the file used for the security datagse. If path is invalid or a NULL is passed + * keys will only be stored in memory. + * + * @param[in] dbPath Path to the file used to store keys in the filesystem, + * if NULL keys will be only stored in memory + * + * @return BLE_ERROR_NONE on success. + */ + virtual ble_error_t setDatabaseFile(const char *dbFilepath = NULL) { + (void)dbFilepath; + return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ + } + /** * Notify all registered onShutdown callbacks that the SecurityManager is * about to be shutdown and clear all SecurityManager state of the diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index f5f060a5e6..4dca909fc7 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -53,6 +53,8 @@ public: const char* db_path = NULL ); + virtual ble_error_t setDatabaseFile(const char *db_path = NULL); + virtual ble_error_t reset(); virtual ble_error_t preserveBondingStateOnReset( diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 9f2f527b0e..588e69ceaa 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -43,29 +43,16 @@ ble_error_t GenericSecurityManager::init( const char* db_path ) { - ble_error_t err = _pal.initialize(); - if (err) { - return err; + ble_error_t result = _pal.initialize(); + if (result != BLE_ERROR_NONE) { + return result; } - if (_db) { - delete _db; + result = setDatabaseFile(db_path); + if (result != BLE_ERROR_NONE) { + return result; } - 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) { - return BLE_ERROR_NO_MEM; - } - - _db->restore(); - _pal.set_io_capability((io_capability_t::type) iocaps); if (passkey) { @@ -115,6 +102,30 @@ ble_error_t GenericSecurityManager::init( return BLE_ERROR_NONE; } +ble_error_t GenericSecurityManager::setDatabaseFile( + const char *db_path +) { + 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) { + return BLE_ERROR_NO_MEM; + } + + _db->restore(); + + return BLE_ERROR_NONE; +} + ble_error_t GenericSecurityManager::reset(void) { _pal.reset(); SecurityManager::reset(); From 9da64e529e96ab7941e89756bc9272adf1bf8ae6 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 18 May 2018 13:46:55 +0100 Subject: [PATCH 246/274] refactor into separate functions for readability and correctness of pal matching db --- features/FEATURE_BLE/ble/SecurityManager.h | 6 +- .../ble/generic/GenericSecurityManager.h | 18 +++- .../source/generic/GenericSecurityManager.cpp | 90 +++++++++++++------ 3 files changed, 82 insertions(+), 32 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 548805c191..358e2478a4 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -464,15 +464,17 @@ public: } /** - * Change the file used for the security datagse. If path is invalid or a NULL is passed + * Change the file used for the security database. If path is invalid or a NULL is passed * keys will only be stored in memory. * + * @note This operation is only allowed with no active connections. + * * @param[in] dbPath Path to the file used to store keys in the filesystem, * if NULL keys will be only stored in memory * * @return BLE_ERROR_NONE on success. */ - virtual ble_error_t setDatabaseFile(const char *dbFilepath = NULL) { + virtual ble_error_t setDatabaseFilepath(const char *dbFilepath = NULL) { (void)dbFilepath; 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 4dca909fc7..b2a2e8ff97 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -53,7 +53,7 @@ public: const char* db_path = NULL ); - virtual ble_error_t setDatabaseFile(const char *db_path = NULL); + virtual ble_error_t setDatabaseFilepath(const char *db_path = NULL); virtual ble_error_t reset(); @@ -265,6 +265,22 @@ public: // private: + + /** + * Initialise the database, if database already exists it will close it and open the new one. + * + * @param db_path path to file to store secure db + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + ble_error_t init_database(const char *db_path = NULL); + + /** + * Generate identity list based on the database of IRK and apply it to the resolving list. + * + * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. + */ + ble_error_t init_resolving_list(); + /** * Generate the CSRK if needed. * diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 588e69ceaa..d09f1d1f64 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -48,7 +48,7 @@ ble_error_t GenericSecurityManager::init( return result; } - result = setDatabaseFile(db_path); + result = init_database(db_path); if (result != BLE_ERROR_NONE) { return result; } @@ -79,49 +79,38 @@ ble_error_t GenericSecurityManager::init( init_signing(); } + init_resolving_list(); + _connection_monitor.set_connection_event_handler(this); _signing_monitor.set_signing_event_handler(this); _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]; - - if (identity_list_p) { - ArrayView identity_list( - identity_list_p, - resolving_list_capacity - ); - - _db->get_identity_list( - mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), - identity_list - ); - } - return BLE_ERROR_NONE; } -ble_error_t GenericSecurityManager::setDatabaseFile( +ble_error_t GenericSecurityManager::setDatabaseFilepath( const char *db_path ) { - if (_db) { - delete _db; + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + + /* operation only allowed with no connections active */ + for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) { + if (_control_blocks[i].connected) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } } - 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(); + ble_error_t result = init_database(db_path); + if (result != BLE_ERROR_NONE) { + return result; } - if (!_db) { - return BLE_ERROR_NO_MEM; + result = init_database(db_path); + if (result != BLE_ERROR_NONE) { + return result; } - _db->restore(); + init_resolving_list(); return BLE_ERROR_NONE; } @@ -779,6 +768,49 @@ ble_error_t GenericSecurityManager::oobReceived( // Helper functions // +ble_error_t GenericSecurityManager::init_database( + const char *db_path +) { + 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) { + return BLE_ERROR_NO_MEM; + } + + _db->restore(); + + return BLE_ERROR_NONE; +} + +ble_error_t GenericSecurityManager::init_resolving_list() { + /* match the resolving list to the currently stored set of IRKs */ + uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity(); + SecurityEntryIdentity_t* identity_list_p = + new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity]; + + if (identity_list_p) { + ArrayView identity_list( + identity_list_p, + resolving_list_capacity + ); + + _db->get_identity_list( + mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), + identity_list + ); + } +} + ble_error_t GenericSecurityManager::init_signing() { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; const csrk_t *pcsrk = _db->get_local_csrk(); From ace491d430ae6264d6f8005aac3544890186f952 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 18 May 2018 13:54:15 +0100 Subject: [PATCH 247/274] remove duplicate call --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index d09f1d1f64..bbfa5d28f6 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -105,11 +105,6 @@ ble_error_t GenericSecurityManager::setDatabaseFilepath( return result; } - result = init_database(db_path); - if (result != BLE_ERROR_NONE) { - return result; - } - init_resolving_list(); return BLE_ERROR_NONE; From cd9f12ab45868656c8acc2ccd85985d0aaf7fce9 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Fri, 18 May 2018 13:59:30 +0100 Subject: [PATCH 248/274] return error codes --- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index bbfa5d28f6..903e271aa9 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -788,6 +788,8 @@ ble_error_t GenericSecurityManager::init_database( } ble_error_t GenericSecurityManager::init_resolving_list() { + if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; + /* match the resolving list to the currently stored set of IRKs */ uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity(); SecurityEntryIdentity_t* identity_list_p = @@ -803,7 +805,11 @@ ble_error_t GenericSecurityManager::init_resolving_list() { mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved), identity_list ); + } else { + return BLE_ERROR_NO_MEM; } + + return BLE_ERROR_NONE; } ble_error_t GenericSecurityManager::init_signing() { From 28766bd873c082ba3878d6deaf11860ed8b82381 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 10:17:44 +0100 Subject: [PATCH 249/274] BLE: Do not pass peer resolvable address in connection event handler --- features/FEATURE_BLE/ble/generic/GenericSecurityManager.h | 3 +-- features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h | 3 +-- .../FEATURE_BLE/source/generic/GenericSecurityManager.cpp | 8 +------- .../TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp | 3 +-- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index b2c74248bc..9624339c18 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -385,8 +385,7 @@ private: const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const Gap::ConnectionParams_t *connection_params, - const BLEProtocol::AddressBytes_t resolved_peer_address + const Gap::ConnectionParams_t *connection_params ); /** diff --git a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h index 0695bf1197..de5a1deb7b 100644 --- a/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h +++ b/features/FEATURE_BLE/ble/pal/ConnectionEventMonitor.h @@ -58,8 +58,7 @@ public: const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const ::Gap::ConnectionParams_t *connection_params, - const BLEProtocol::AddressBytes_t resolved_peer_address + const ::Gap::ConnectionParams_t *connection_params ) = 0; /** diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 9fef7c4cc8..f3bf741fe5 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -968,8 +968,7 @@ void GenericSecurityManager::on_connected( const BLEProtocol::AddressBytes_t peer_address, BLEProtocol::AddressType_t local_address_type, const BLEProtocol::AddressBytes_t local_address, - const Gap::ConnectionParams_t *connection_params, - const BLEProtocol::AddressBytes_t resolved_peer_address + const Gap::ConnectionParams_t *connection_params ) { MBED_ASSERT(_db); ControlBlock_t *cb = acquire_control_block(connection); @@ -981,11 +980,6 @@ void GenericSecurityManager::on_connected( cb->local_address = local_address; cb->is_master = (role == Gap::CENTRAL); - // normalize the address - if (resolved_peer_address && resolved_peer_address != ble::address_t()) { - peer_address = resolved_peer_address; - } - // get the associated db handle and the distribution flags if any cb->db_entry = _db->open_entry(peer_address_type, peer_address); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index aa6884cb85..72733a4715 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -1393,8 +1393,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t peer_address, own_addr_type, own_address.data(), - reinterpret_cast(&(evt.conn_params)), - peer_resolvable_address + reinterpret_cast(&(evt.conn_params)) ); } From d962fc0174529684886b4ad1af3776343a727ea4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 10:20:43 +0100 Subject: [PATCH 250/274] BLE: factor code in GAP. --- .../TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 72733a4715..e7506b5fae 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -44,12 +44,8 @@ nRF5xSecurityManager& get_sm() { ble_error_t set_private_resolvable_address() { #if (NRF_SD_BLE_API_VERSION <= 2) - ble_gap_addr_t addr = { - BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE - }; - - sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); - return BLE_ERROR_NONE; + ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE }; + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); #else ble_gap_privacy_params_t privacy_config = { 0 }; uint32_t err = sd_ble_gap_privacy_get(&privacy_config); @@ -59,14 +55,14 @@ ble_error_t set_private_resolvable_address() { privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; err = sd_ble_gap_privacy_set(&privacy_config); - return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; #endif + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; } ble_error_t set_private_non_resolvable_address() { #if (NRF_SD_BLE_API_VERSION <= 2) ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; - sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); #else ble_gap_privacy_params_t privacy_config = { 0 }; uint32_t err = sd_ble_gap_privacy_get(&privacy_config); @@ -76,8 +72,8 @@ ble_error_t set_private_non_resolvable_address() { privacy_config.private_addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE; err = sd_ble_gap_privacy_set(&privacy_config); - return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; #endif + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; } bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { From 4c1a309117586fa533db477894f1dd24dbb63a41 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 10:22:01 +0100 Subject: [PATCH 251/274] Nordic BLE: Set own resolvable address to NULL. This address is not accessible to the application. --- .../TARGET_NRF52/source/nRF5xGap.cpp | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index e7506b5fae..7e72e35a22 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -1322,7 +1322,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t // deal with own address LegacyAddressType_t own_addr_type; ble::address_t own_address; - ble::address_t own_resolvable_address; + const uint8_t* own_resolvable_address = NULL; #if (NRF_SD_BLE_API_VERSION <= 2) if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { @@ -1335,14 +1335,6 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t getAddress(&own_addr_type, own_address.data()); #endif - if (_privacy_enabled) { - // swap own address with own resolvable address as when privacy is - // enabled own_address is invalid and the address returned by getAddress - // is the resolvable one. - std::swap(own_address, own_resolvable_address); - own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; - } - #if (NRF_SD_BLE_API_VERSION <= 2) bool private_peer_known = evt.irk_match; #else @@ -1374,11 +1366,11 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t private_peer_known, evt.peer_addr.addr_type ); + // NOTE: when privacy is enabled, the only address returned is the resolved - // address; set peer and resolved address to the same value in such case. + // address. const uint8_t* peer_address = evt.peer_addr.addr; - const uint8_t* peer_resolvable_address = - private_peer_known ? peer_address : NULL; + const uint8_t* peer_resolvable_address = NULL; // notify internal event handler before applying the resolution strategy if (_connection_event_handler) { @@ -1422,7 +1414,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t own_address.data(), reinterpret_cast(&(evt.conn_params)), peer_resolvable_address, - own_resolvable_address.data() + own_resolvable_address ); } From 14a1095c31e8583ccf4a6ca1acc17eb9c4ab57ec Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 10:34:09 +0100 Subject: [PATCH 252/274] Nordic BLE: Disable secure connection support on NRF51. --- .../TARGET_NRF51/source/nRF5xPalSecurityManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp index 43033eb1f0..287ce267b5 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp @@ -373,7 +373,7 @@ ble_error_t nRF5xSecurityManager::cancel_pairing( ble_error_t nRF5xSecurityManager::get_secure_connections_support( bool &enabled ) { - enabled = true; + enabled = false; return BLE_ERROR_NONE; } From 17e8ed9401abf725069109ce6e303cda0a4f5afe Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 21 May 2018 11:34:40 +0100 Subject: [PATCH 253/274] forward resolving list init --- .../source/generic/GenericSecurityManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 903e271aa9..29adce2ba4 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -42,13 +42,14 @@ ble_error_t GenericSecurityManager::init( bool signing, const char* db_path ) { - ble_error_t result = _pal.initialize(); + if (result != BLE_ERROR_NONE) { return result; } result = init_database(db_path); + if (result != BLE_ERROR_NONE) { return result; } @@ -79,12 +80,17 @@ ble_error_t GenericSecurityManager::init( init_signing(); } - init_resolving_list(); - _connection_monitor.set_connection_event_handler(this); _signing_monitor.set_signing_event_handler(this); _pal.set_event_handler(this); + result = init_resolving_list(); + + if (result != BLE_ERROR_NONE) { + delete _db; + return result; + } + return BLE_ERROR_NONE; } @@ -766,9 +772,7 @@ ble_error_t GenericSecurityManager::oobReceived( ble_error_t GenericSecurityManager::init_database( const char *db_path ) { - if (_db) { - delete _db; - } + delete _db; FILE* db_file = FileSecurityDb::open_db_file(db_path); From 62ba2201002ed9f1c2116b145719aa88c0599209 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Mon, 21 May 2018 11:42:32 +0100 Subject: [PATCH 254/274] doxygen fix --- features/FEATURE_BLE/ble/SecurityManager.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/ble/SecurityManager.h b/features/FEATURE_BLE/ble/SecurityManager.h index 358e2478a4..6f9f4c83ed 100644 --- a/features/FEATURE_BLE/ble/SecurityManager.h +++ b/features/FEATURE_BLE/ble/SecurityManager.h @@ -441,7 +441,7 @@ 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 file used to store keys in the filesystem, + * @param[in] dbFilepath Path to the file used to store keys in the filesystem, * if NULL keys will be only stored in memory * * @@ -469,7 +469,7 @@ public: * * @note This operation is only allowed with no active connections. * - * @param[in] dbPath Path to the file used to store keys in the filesystem, + * @param[in] dbFilepath Path to the file used to store keys in the filesystem, * if NULL keys will be only stored in memory * * @return BLE_ERROR_NONE on success. From 57ffa14b4baa6c6eaaf8e3a77d1e0dda83774abf Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 13:21:46 +0100 Subject: [PATCH 255/274] Nordic BLE: Backport privacy backward compatibility to NRF51 --- .../TARGET_NRF51/source/nRF5xGap.cpp | 409 ++++++++---------- .../TARGET_NRF51/source/nRF5xGap.h | 36 +- 2 files changed, 186 insertions(+), 259 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp index 9c3566625a..d6dfb883cf 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp @@ -32,6 +32,10 @@ using ble::pal::vendor::nordic::nRF5xSecurityManager; typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t; using ble::ArrayView; using ble::pal::advertising_peer_address_type_t; +using ble::peer_address_type_t; + +typedef BLEProtocol::AddressType LegacyAddressType; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; namespace { @@ -39,14 +43,16 @@ nRF5xSecurityManager& get_sm() { return nRF5xSecurityManager::get_security_manager(); } -void set_private_resolvable_address() { +ble_error_t set_private_resolvable_address() { ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE }; - sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; } -void set_private_non_resolvable_address() { +ble_error_t set_private_non_resolvable_address() { ble_gap_addr_t addr = { BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE }; - sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_AUTO, &addr); + return err ? BLE_ERROR_UNSPECIFIED : BLE_ERROR_NONE; } bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { @@ -59,29 +65,24 @@ bool is_advertising_non_connectable(const GapAdvertisingParams ¶ms) { } } -bool is_identity_address(BLEProtocol::AddressType_t address_type) { - switch (address_type) { - case BLEProtocol::AddressType::PUBLIC_IDENTITY: - case BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY: - return true; - default: - return false; - } +bool is_identity_address(peer_address_type_t address_type) { + return address_type == peer_address_type_t::PUBLIC_IDENTITY || + address_type == peer_address_type_t::RANDOM_STATIC_IDENTITY; } -BLEProtocol::AddressType_t convert_nordic_address(uint8_t address) { +peer_address_type_t convert_nordic_address(uint8_t address) { if (address == BLE_GAP_ADDR_TYPE_PUBLIC) { - return BLEProtocol::AddressType::PUBLIC; + return peer_address_type_t::PUBLIC; } else { - return BLEProtocol::AddressType::RANDOM; + return peer_address_type_t::RANDOM; } } -BLEProtocol::AddressType_t convert_identity_address(advertising_peer_address_type_t address) { +peer_address_type_t convert_identity_address(advertising_peer_address_type_t address) { if (address == advertising_peer_address_type_t::PUBLIC_ADDRESS) { - return BLEProtocol::AddressType::PUBLIC_IDENTITY; + return peer_address_type_t::PUBLIC_IDENTITY; } else { - return BLEProtocol::AddressType::RANDOM_STATIC_IDENTITY; + return peer_address_type_t::RANDOM_STATIC_IDENTITY; } } @@ -103,7 +104,7 @@ nRF5xGap::nRF5xGap() : Gap(), _privacy_enabled(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), - _non_private_type(BLEProtocol::AddressType::RANDOM) + _non_private_address_type(LegacyAddressType::RANDOM_STATIC) { m_connectionHandle = BLE_CONN_HANDLE_INVALID; } @@ -259,12 +260,10 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (advertisingPolicyMode != Gap::ADV_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; - } + whitelist.addr_count = whitelistAddressesSize; + + for (uint32_t i = 0; i < whitelistAddressesSize; ++i) { + whitelistAddressPtrs[i] = &whitelistAddresses[i]; } if (_privacy_enabled) { @@ -295,15 +294,12 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) /* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */ /* Start Advertising */ - - adv_para.type = params.getAdvertisingType(); adv_para.p_peer_addr = NULL; // Undirected advertisement adv_para.fp = advertisingPolicyMode; adv_para.interval = params.getIntervalInADVUnits(); // advertising interval (in units of 0.625 ms) adv_para.timeout = params.getTimeout(); - err = sd_ble_gap_adv_start(&adv_para); switch(err) { case ERROR_NONE: @@ -319,7 +315,6 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms) #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) { - ble_gap_scan_params_t scanParams; #if (NRF_SD_BLE_API_VERSION <= 2) @@ -333,15 +328,26 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams) whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; - } + whitelist.addr_count = whitelistAddressesSize; + + for (uint32_t i = 0; i < whitelistAddressesSize; ++i) { + whitelistAddressPtrs[i] = &whitelistAddresses[i]; } - // FIXME: fill the irk list once addresses are resolved by the softdevice. + if (_privacy_enabled) { + if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) { + ArrayView entries = get_sm().get_resolving_list(); + + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); + + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); + } + whitelist.irk_count = limit; + } + } scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ @@ -408,11 +414,59 @@ ble_error_t nRF5xGap::stopAdvertising(void) return BLE_ERROR_NONE; } -ble_error_t nRF5xGap::connect(const Address_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t *connectionParams, - const GapScanningParams *scanParamsIn) -{ +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + peer_address_type_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { + // NOTE: Nordic address type is an closer to LegacyAddressType: resolved + // address are treaded either as PUBLIC or RANDOM STATIC adresses. + // The idea is to get the conversion done here and call the legacy function. + + LegacyAddressType_t legacy_address; + + switch (peerAddrType.value()) { + case peer_address_type_t::PUBLIC: + case peer_address_type_t::PUBLIC_IDENTITY: + legacy_address = LegacyAddressType::PUBLIC; + break; + case peer_address_type_t::RANDOM_STATIC_IDENTITY: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case peer_address_type_t::RANDOM: { + RandomAddressType_t random_address_type(RandomAddressType_t::STATIC); + ble_error_t err = getRandomAddressType(peerAddr, &random_address_type); + if (err) { + return err; + } + switch (random_address_type.value()) { + case RandomAddressType_t::STATIC: + legacy_address = LegacyAddressType::RANDOM_STATIC; + break; + case RandomAddressType_t::NON_RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; + break; + case RandomAddressType_t::RESOLVABLE_PRIVATE: + legacy_address = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + break; + default: + return BLE_ERROR_UNSPECIFIED; + } + } break; + default: + return BLE_ERROR_INVALID_PARAM; + } + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn); +} + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn +) { ble_gap_addr_t addr; ble_gap_addr_t* addr_ptr = &addr; addr.addr_type = peerAddrType; @@ -444,40 +498,21 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr, whitelist.addr_count = 0; whitelist.irk_count = 0; - /* Add missing IRKs to whitelist from the bond table held by the SoftDevice */ - if (scanningPolicyMode != Gap::SCAN_POLICY_IGNORE_WHITELIST) { - ble_error_t error = generateStackWhitelist(whitelist); - if (error != BLE_ERROR_NONE) { - return error; - } - } scanParams.selective = scanningPolicyMode; /**< If 1, ignore unknown devices (non whitelisted). */ scanParams.p_whitelist = &whitelist; /**< Pointer to whitelist, NULL if none is given. */ if (_privacy_enabled) { - // configure the "whitelist" with the IRK associated with the identity - // address in input. - if (is_identity_address(peerAddrType)) { + if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE) { ArrayView entries = get_sm().get_resolving_list(); - size_t i; - for (i = 0; i < entries.size(); ++i) { - const ble::address_t& entry_address = entries[i].peer_identity_address; + size_t limit = std::min( + entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE + ); - // entry found; fill the whitelist and invalidate addr_ptr - if (memcmp(entry_address.data(), peerAddr, entry_address.size_) == 0) { - whitelist.pp_irks[0] = (ble_gap_irk_t*) entries[i].peer_irk.data(); - whitelist.irk_count = 1; - scanParams.selective = 1; - addr_ptr = NULL; - break; - } - } - - // Occur only if the address in input hasn't been resolved. - if (i == entries.size()) { - return BLE_ERROR_INVALID_PARAM; + for (size_t i = 0; i < limit; ++i) { + whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); } + whitelist.irk_count = limit; } set_private_resolvable_address(); @@ -666,11 +701,11 @@ uint16_t nRF5xGap::getConnectionHandle(void) @endcode */ /**************************************************************************/ -ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) +ble_error_t nRF5xGap::setAddress(LegacyAddressType_t type, const Address_t address) { - using BLEProtocol::AddressType; - - if (type != AddressType::PUBLIC || type != AddressType::RANDOM_STATIC) { + if (type != LegacyAddressType::PUBLIC && + type != LegacyAddressType::RANDOM_STATIC + ) { return BLE_ERROR_INVALID_PARAM; } @@ -680,30 +715,41 @@ ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address) ble_gap_addr_t dev_addr; memcpy(dev_addr.addr, address, ADDR_LEN); - if (type == AddressType::PUBLIC) { + if (type == LegacyAddressType::PUBLIC) { dev_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; } else { dev_addr.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_STATIC; } #if (NRF_SD_BLE_API_VERSION <= 2) - ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); + uint32_t err = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr); #else - // FIXME is there any reason to use the pm ? - ble_gap_privacy_params_t privacy_params = {0}; - privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF; - - ASSERT_INT(ERROR_NONE, pm_id_addr_set(&dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE); - ASSERT_INT(ERROR_NONE, pm_privacy_set(&privacy_params), BLE_ERROR_PARAM_OUT_OF_RANGE); + uint32_t err = sd_ble_gap_addr_set(&dev_addr); #endif - return BLE_ERROR_NONE; + switch (err) { + case NRF_SUCCESS: + return BLE_ERROR_NONE; + case NRF_ERROR_INVALID_ADDR: + return BLE_ERROR_INVALID_PARAM; + case BLE_ERROR_GAP_INVALID_BLE_ADDR: + return BLE_ERROR_PARAM_OUT_OF_RANGE; + case NRF_ERROR_BUSY: + return BLE_STACK_BUSY; + case NRF_ERROR_INVALID_STATE: + return BLE_ERROR_INVALID_STATE; + default: + return BLE_ERROR_UNSPECIFIED; + } } ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) { - ble_gap_addr_t dev_addr; + if (typeP == NULL || address == NULL) { + return BLE_ERROR_INVALID_PARAM; + } + ble_gap_addr_t dev_addr; #if (NRF_SD_BLE_API_VERSION <= 2) if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) { #else @@ -712,17 +758,20 @@ ble_error_t nRF5xGap::getAddress(AddressType_t *typeP, Address_t address) return BLE_ERROR_PARAM_OUT_OF_RANGE; } - if (typeP != NULL) { - if (dev_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC){ - *typeP = BLEProtocol::AddressType::PUBLIC; - } else { - *typeP = BLEProtocol::AddressType::RANDOM; - } + switch (dev_addr.addr_type) { + case BLE_GAP_ADDR_TYPE_PUBLIC: + *typeP = LegacyAddressType::PUBLIC; + break; + + case BLE_GAP_ADDR_TYPE_RANDOM_STATIC: + *typeP = LegacyAddressType::RANDOM_STATIC; + break; + + default: + return BLE_ERROR_INVALID_STATE; } - if (address != NULL) { - memcpy(address, dev_addr.addr, ADDR_LEN); - } + memcpy(address, dev_addr.addr, ADDR_LEN); return BLE_ERROR_NONE; } @@ -849,9 +898,7 @@ ble_error_t nRF5xGap::getWhitelist(Gap::Whitelist_t &whitelistOut) const uint32_t i; for (i = 0; i < whitelistAddressesSize && i < whitelistOut.capacity; ++i) { memcpy( &whitelistOut.addresses[i].address, &whitelistAddresses[i].addr, sizeof(whitelistOut.addresses[0].address)); - whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); - - + whitelistOut.addresses[i].type = static_cast (whitelistAddresses[i].addr_type); } whitelistOut.size = i; @@ -896,7 +943,9 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn) /* Test for invalid parameters before we change the internal state */ for (uint32_t i = 0; i < whitelistIn.size; ++i) { - if (whitelistIn.addresses[i].type == BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE) { + if (whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE || + whitelistIn.addresses[i].type == LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE + ) { /* This is not allowed because it is completely meaningless */ return BLE_ERROR_INVALID_PARAM; } @@ -1052,24 +1101,38 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const return Gap::INIT_POLICY_IGNORE_WHITELIST; } -ble_error_t nRF5xGap::enablePrivacy(bool enable) +ble_error_t nRF5xGap::enablePrivacy(bool enable_privacy) { - if (enable == _privacy_enabled) { + if (enable_privacy == _privacy_enabled) { return BLE_ERROR_NONE; } ble_error_t err = BLE_ERROR_UNSPECIFIED; - if (enable == false) { - err = setAddress(_non_private_type, _non_private_address); + if (enable_privacy == false) { + err = setAddress(_non_private_address_type, _non_private_address); } else { - err = getAddress(&_non_private_type, _non_private_address); + err = getAddress(&_non_private_address_type, _non_private_address); } if (err) { return err; } - _privacy_enabled = enable; +#if (NRF_SD_BLE_API_VERSION > 2) + ble_gap_privacy_params_t privacy_config = { 0 }; + if (sd_ble_gap_privacy_get(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } + + privacy_config.privacy_mode = enable_privacy ? + BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY : + BLE_GAP_PRIVACY_MODE_OFF; + if (sd_ble_gap_privacy_set(&privacy_config)) { + return BLE_ERROR_UNSPECIFIED; + } +#endif + + _privacy_enabled = enable_privacy; return BLE_ERROR_NONE; } @@ -1101,116 +1164,6 @@ ble_error_t nRF5xGap::getCentralPrivacyConfiguration( return BLE_ERROR_NONE; } -#if (NRF_SD_BLE_API_VERSION <= 2) -/**************************************************************************/ -/*! - @brief Helper function used to populate the ble_gap_whitelist_t that - will be used by the SoftDevice for filtering requests. - @returns \ref ble_error_t - @retval BLE_ERROR_NONE - Everything executed properly - @retval BLE_ERROR_INVALID_STATE - The internal stack was not initialized correctly. - @note Both the SecurityManager and Gap must initialize correctly for - this function to succeed. - @note This function is needed because for the BLE API the whitelist - is just a collection of keys, but for the stack it also includes - the IRK table. - @section EXAMPLE - @code - @endcode -*/ -/**************************************************************************/ -ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist) -{ - return BLE_ERROR_NOT_IMPLEMENTED; -} -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - -/** - * Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice. - * - * Gap::setWhitelist provides the base for preparation of these settings. - * This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table. - * Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice) - * are passed to the identities list (intended to be passed to the Softdevice). - * - * @param[out] gapAdrHelper Reference to the struct for storing settings. - */ - -ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - BLE_ERROR_NOT_IMPLEMENTED; -} - -ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper) -{ - uint32_t retc; - - if (gapAdrHelper.identities_cnt == 0) { - retc = sd_ble_gap_device_identities_set(NULL, NULL, 0); - } else { - ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i) - { - pp_identities[i] = &gapAdrHelper.identities[i]; - } - - retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt); - } - - if (retc == NRF_SUCCESS) { - if (gapAdrHelper.addrs_cnt == 0) { - retc = sd_ble_gap_whitelist_set(NULL, 0); - } else { - ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - - for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i) - { - pp_addrs[i] = &gapAdrHelper.addrs[i]; - } - - retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt); - } - } - - switch(retc) { - case NRF_SUCCESS: - return BLE_ERROR_NONE; - - case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared. - case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared. - return BLE_ERROR_ALREADY_INITIALIZED; - - case NRF_ERROR_INVALID_ADDR: - case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied. - case NRF_ERROR_DATA_SIZE: - case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address. - return BLE_ERROR_INVALID_PARAM; - - default: - return BLE_ERROR_UNSPECIFIED; - } -} - -ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack() -{ - GapWhiteAndIdentityList_t whiteAndIdentityList; - uint32_t err; - - err = getStackWhiteIdentityList(whiteAndIdentityList); - - if (err != BLE_ERROR_NONE) { - return (ble_error_t)err; - } - - return applyWhiteIdentityList(whiteAndIdentityList); -} -#endif - void nRF5xGap::set_connection_event_handler( ConnectionEventMonitor::EventHandler* connection_event_handler ) { @@ -1241,36 +1194,44 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t setConnectionHandle(handle); // deal with own address - AddressType_t own_addr_type; + LegacyAddressType_t own_addr_type; Address_t own_address; const uint8_t* own_resolvable_address = NULL; #if (NRF_SD_BLE_API_VERSION <= 2) - if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { - own_addr_type = AddressType::PUBLIC; + if (_privacy_enabled) { + own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; } else { - own_addr_type = AddressType::RANDOM; + if (evt.own_addr.addr_type == BLE_GAP_ADDR_TYPE_PUBLIC) { + own_addr_type = LegacyAddressType::PUBLIC; + } else { + own_addr_type = LegacyAddressType::RANDOM_STATIC; + } } + + // FIXME: is it the resolvable address or the identity address ? memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); #else gap.getAddress(&addr_type, own_address); #endif - if (_privacy_enabled) { - own_resolvable_address = own_address; - } - // deal with the peer address: If privacy is enabled then the softdevice // indicates if the address has been resolved or not. If the address has // been resolved then the identity address should be passed to the application. // Depending on the privacy chosen by the application, connection request // from privacy enabled peers may trigger a disconnection, the pairing procedure // or the authentication procedure. - AddressType_t peer_addr_type; + peer_address_type_t peer_addr_type(peer_address_type_t::PUBLIC); const uint8_t* peer_address; const uint8_t* peer_resolvable_address; - if (evt.irk_match) { +#if (NRF_SD_BLE_API_VERSION <= 2) + bool private_peer_known = evt.irk_match; +#else + bool private_peer_known = evt.peer_addr.addr_id_peer; +#endif + + if (private_peer_known) { const resolving_list_entry_t* entry = get_sm().resolve_address( evt.peer_addr.addr ); @@ -1311,14 +1272,14 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t } // Apply authentication strategy before application notification - if (!evt.irk_match && + if (!private_peer_known && _privacy_enabled && evt.role == BLE_GAP_ROLE_PERIPH && evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE ) { switch (_peripheral_privacy_configuration.resolution_strategy) { case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: - nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle); + nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle); break; case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: @@ -1344,9 +1305,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t } void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { - using BLEProtocol::AddressType; - - AddressType_t peer_addr_type; + peer_address_type_t peer_addr_type(peer_address_type_t::PUBLIC); const uint8_t* peer_address = evt.peer_addr.addr; if (_privacy_enabled && diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h index cb12a610f2..d595de6278 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h @@ -78,6 +78,7 @@ public: virtual ble_error_t startAdvertising(const GapAdvertisingParams &); virtual ble_error_t stopAdvertising(void); + virtual ble_error_t connect(const Address_t, ble::peer_address_type_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); @@ -159,39 +160,6 @@ private: uint8_t whitelistAddressesSize; ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE]; -#if (NRF_SD_BLE_API_VERSION <= 2) - /* - * An internal function used to populate the ble_gap_whitelist_t that will be used by - * the SoftDevice for filtering requests. This function is needed because for the BLE - * API the whitelist is just a collection of keys, but for the stack it also includes - * the IRK table. - */ - ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist); -#endif - -#if (NRF_SD_BLE_API_VERSION >= 3) - /* internal type for passing a whitelist and a identities list. */ - typedef struct - { - ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE]; - uint32_t addrs_cnt; - - ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE]; - uint32_t identities_cnt; - } GapWhiteAndIdentityList_t; - - /* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/ - ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/ - ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList); - - /* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice. - * - * This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */ - ble_error_t updateWhiteAndIdentityListInStack(void); -#endif - private: bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ Timeout radioNotificationTimeout; @@ -303,7 +271,7 @@ private: bool _privacy_enabled; PeripheralPrivacyConfiguration_t _peripheral_privacy_configuration; CentralPrivacyConfiguration_t _central_privacy_configuration; - AddressType_t _non_private_type; + AddressType_t _non_private_address_type; Address_t _non_private_address; /* From cbba6dd0d607da330b721ca722085405fc5004e5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 13:22:31 +0100 Subject: [PATCH 256/274] BLE PAL: Update connection event to support enhanced connection events. --- features/FEATURE_BLE/ble/pal/GapEvents.h | 83 +++++++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/features/FEATURE_BLE/ble/pal/GapEvents.h b/features/FEATURE_BLE/ble/pal/GapEvents.h index a406d6cdcc..728205479f 100644 --- a/features/FEATURE_BLE/ble/pal/GapEvents.h +++ b/features/FEATURE_BLE/ble/pal/GapEvents.h @@ -140,7 +140,6 @@ struct GapConnectionCompleteEvent : public GapEvent { * @param supervision_timeout Supervision timeout of the connection. It * shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. * - * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.1 LE Connection Complete Event * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection * Complete Event */ @@ -153,6 +152,69 @@ struct GapConnectionCompleteEvent : public GapEvent { uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout + ) : + GapEvent(GapEventType::CONNECTION_COMPLETE), + status(status), + connection_handle(connection_handle), + role(role), + peer_address_type( + peer_address_type == advertising_peer_address_type_t::PUBLIC_ADDRESS ? + peer_address_type_t::PUBLIC : + peer_address_type_t::RANDOM + ), + peer_address(peer_address), + connection_interval(connection_interval), + connection_latency(connection_latency), + supervision_timeout(supervision_timeout), + local_resolvable_private_address(), + peer_resolvable_private_address() { + } + + /** + * Construct a new GapConnectionCompleteEvent. + * + * @param status Status of the operation: 0x00 in case of success otherwise + * the error code associated with the failure. + * + * @param connection_handle handle of the connection created. This handle + * will be used to address the connection in any connection oriented + * operation. + * + * @param role Role of the LE subsystem in the connection. + * + * @param address_type Type of address used by the peer for this connection. + * + * @param address Address of the peer used to establish the connection. + * + * @param connection_interval Connection interval used on this connection. + * It shall be in a range [0x0006 : 0x0C80]. A unit is equal to 1.25ms. + * + * @param connection_latency Number of connection events the slave can + * drop. + * + * @param supervision_timeout Supervision timeout of the connection. It + * shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. + * + * @param local_resolvable_private_address Resolvable private address used + * by the local device to establish the connection. + * + * @param peer_resolvable_private_address Resolvable private address used + * by the peer to establish the connection. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE Enhanced Connection + * Complete Event + */ + GapConnectionCompleteEvent( + uint8_t status, + connection_handle_t connection_handle, + connection_role_t role, + peer_address_type_t peer_address_type, + const address_t& peer_address, + uint16_t connection_interval, + uint16_t connection_latency, + uint16_t supervision_timeout, + const address_t& local_resolvable_private_address, + const address_t& peer_resolvable_private_address ) : GapEvent(GapEventType::CONNECTION_COMPLETE), status(status), @@ -162,9 +224,12 @@ struct GapConnectionCompleteEvent : public GapEvent { peer_address(peer_address), connection_interval(connection_interval), connection_latency(connection_latency), - supervision_timeout(supervision_timeout) { + supervision_timeout(supervision_timeout), + local_resolvable_private_address(local_resolvable_private_address), + peer_resolvable_private_address(peer_resolvable_private_address) { } + /* * @param status Indicate if the connection succesfully completed or not: * - 0: Connection successfuly completed @@ -188,7 +253,7 @@ struct GapConnectionCompleteEvent : public GapEvent { /** * Peer address type. */ - const advertising_peer_address_type_t peer_address_type; + const peer_address_type_t peer_address_type; /** * Peer address. @@ -211,6 +276,18 @@ struct GapConnectionCompleteEvent : public GapEvent { * It shall be in the range [0x000A : 0x0C80] where a unit represent 10ms. */ const uint16_t supervision_timeout; + + /** + * Resolvable private address of the local device. + * Set to all 0 if not available. + */ + const address_t local_resolvable_private_address; + + /** + * Resolvable private address of the peer. + * Set to all 0 if not available. * + */ + const address_t peer_resolvable_private_address; }; From cc286fe84c510e7d543f075985a325b750525bde Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 13:22:53 +0100 Subject: [PATCH 257/274] BLE: Cordio pal: Handle enhanced connection events. --- features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h index ee2c4f2f57..52fae1eed3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalGap.h @@ -393,11 +393,13 @@ private: // note the usage of the stack handle, not the HCI handle conn_evt->hdr.param, (connection_role_t::type) conn_evt->role, - (advertising_peer_address_type_t::type) conn_evt->addrType, + (peer_address_type_t::type) conn_evt->addrType, conn_evt->peerAddr, conn_evt->connInterval, conn_evt->connLatency, - conn_evt->supTimeout + conn_evt->supTimeout, + conn_evt->localRpa, + conn_evt->peerRpa ); } }; From bdad5d64962ae2d68a75a327d891b96740bed522 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 13:29:06 +0100 Subject: [PATCH 258/274] BLE Generic: Handle peer address type backward compatibility. --- features/FEATURE_BLE/ble/generic/GenericGap.h | 16 +- .../FEATURE_BLE/source/generic/GenericGap.cpp | 279 ++++++++++-------- 2 files changed, 178 insertions(+), 117 deletions(-) diff --git a/features/FEATURE_BLE/ble/generic/GenericGap.h b/features/FEATURE_BLE/ble/generic/GenericGap.h index 18e9196b6e..33fa638fda 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGap.h +++ b/features/FEATURE_BLE/ble/generic/GenericGap.h @@ -113,6 +113,16 @@ public: */ virtual ble_error_t stopScan(); + /** + * @see Gap::connect + */ + virtual ble_error_t connect( + const BLEProtocol::AddressBytes_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams + ); + /** * @see Gap::connect */ @@ -295,11 +305,13 @@ public: void processConnectionEvent( Handle_t handle, Role_t role, - BLEProtocol::AddressType_t peerAddrType, + peer_address_type_t peerAddrType, const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr ); /** diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index c05ec5cd64..904e8caf9f 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -31,6 +31,10 @@ namespace ble { namespace generic { +using pal::connection_peer_address_type_t; +typedef BLEProtocol::AddressType_t LegacyAddressType_t; +typedef BLEProtocol::AddressType LegacyAddressType; + namespace { // Constants @@ -353,7 +357,7 @@ static bool is_in_whitelist( /* * Convert a BLEProtocol::AddressType_t into a pal::whitelist_address_type_t. */ -static pal::whitelist_address_type_t to_device_address_type( +static pal::whitelist_address_type_t to_whitelist_address_type( BLEProtocol::AddressType_t address_type ) { return (address_type == BLEProtocol::AddressType::PUBLIC) ? @@ -361,6 +365,18 @@ static pal::whitelist_address_type_t to_device_address_type( pal::whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; } +/* + * Convert a BLEProtocol::AddressType_t into a pal::peer_address_type + */ +static peer_address_type_t to_peer_address_type( + LegacyAddressType_t address_type +) { + return (address_type == LegacyAddressType::PUBLIC) ? + peer_address_type_t::PUBLIC : + peer_address_type_t::RANDOM; +} + + /* * Return true if the advertising parameters are valid. */ @@ -388,7 +404,7 @@ GenericGap::GenericGap( _pal_gap(pal_gap), _gap_service(generic_access_service), _pal_sm(pal_sm), - _address_type(BLEProtocol::AddressType::PUBLIC), + _address_type(LegacyAddressType::PUBLIC), _initiator_policy_mode(pal::initiator_policy_t::NO_FILTER), _scanning_filter_policy(pal::scanning_filter_policy_t::NO_FILTER), _advertising_filter_policy(pal::advertising_filter_policy_t::NO_FILTER), @@ -414,16 +430,16 @@ GenericGap::~GenericGap() } ble_error_t GenericGap::setAddress( - BLEProtocol::AddressType_t type, - const BLEProtocol::AddressBytes_t address + LegacyAddressType_t type, + const Address_t address ) { switch (type) { - case BLEProtocol::AddressType::PUBLIC: + case LegacyAddressType::PUBLIC: // The public address cannot be set, just set the type to public _address_type = type; return BLE_ERROR_NONE; - case BLEProtocol::AddressType::RANDOM_STATIC: { + case LegacyAddressType::RANDOM_STATIC: { if (is_random_static_address(address) == false) { return BLE_ERROR_INVALID_PARAM; } @@ -441,8 +457,8 @@ ble_error_t GenericGap::setAddress( return BLE_ERROR_NONE; } - case BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE: - case BLEProtocol::AddressType::RANDOM_PRIVATE_NON_RESOLVABLE: + case LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE: + case LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE: // Note: it is not allowed to set directly these addresses // privacy management handled it for users. return BLE_ERROR_INVALID_PARAM; @@ -453,13 +469,13 @@ ble_error_t GenericGap::setAddress( } ble_error_t GenericGap::getAddress( - BLEProtocol::AddressType_t *type, - BLEProtocol::AddressBytes_t address + LegacyAddressType_t *type, + Address_t address ) { *type = _address_type; ble::address_t address_value; - if (_address_type == BLEProtocol::AddressType::PUBLIC) { + if (_address_type == LegacyAddressType::PUBLIC) { address_value = _pal_gap.get_device_address(); } else { address_value = _pal_gap.get_random_address(); @@ -514,10 +530,10 @@ ble_error_t GenericGap::stopScan() } ble_error_t GenericGap::connect( - const BLEProtocol::AddressBytes_t peerAddr, - BLEProtocol::AddressType_t peerAddrType, - const ConnectionParams_t* connectionParams, - const GapScanningParams* scanParams + const Address_t peerAddr, + PeerAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParams ) { if (connectionParams == NULL) { connectionParams = &default_connection_params; @@ -535,8 +551,6 @@ ble_error_t GenericGap::connect( return BLE_ERROR_PARAM_OUT_OF_RANGE; } - // TODO fix upper layer API, address type factorization is incorrect. - // Force scan stop before initiating the scan used for connection stopScan(); @@ -544,7 +558,7 @@ ble_error_t GenericGap::connect( scanParams->getInterval(), scanParams->getWindow(), _initiator_policy_mode, - (pal::connection_peer_address_type_t::type) peerAddrType, + (pal::connection_peer_address_type_t::type) peerAddrType.value(), ble::address_t(peerAddr), get_own_address_type(CENTRAL_CONNECTION /* requires resolvable address */), connectionParams->minConnectionInterval, @@ -556,6 +570,21 @@ ble_error_t GenericGap::connect( ); } + +ble_error_t GenericGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t* connectionParams, + const GapScanningParams* scanParams +) { + return connect( + peerAddr, + to_peer_address_type(peerAddrType), + connectionParams, + scanParams + ); +} + ble_error_t GenericGap::disconnect(Handle_t connectionHandle, DisconnectionReason_t reason) { if (is_disconnection_reason_valid(reason) == false) { @@ -706,7 +735,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { ble_error_t err = _pal_gap.remove_device_from_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); @@ -717,7 +746,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -733,7 +762,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, _whitelist) == false) { ble_error_t err = _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); @@ -745,7 +774,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, _whitelist) == false) { _pal_gap.remove_device_from_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -757,7 +786,7 @@ ble_error_t GenericGap::setWhitelist(const Whitelist_t &whitelist) if (is_in_whitelist(device, whitelist) == false) { _pal_gap.add_device_to_whitelist( - to_device_address_type(device.type), + to_whitelist_address_type(device.type), device.address ); } @@ -961,9 +990,11 @@ ble_error_t GenericGap::startAdvertising(const GapAdvertisingParams& params) // We can only use non resolvable addresses if the device is non connectable AddressUseType_t address_use_type = - ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) - || (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) - ? PERIPHERAL_NON_CONNECTABLE : PERIPHERAL_CONNECTABLE; + ((params.getAdvertisingType() == GapAdvertisingParams::ADV_SCANNABLE_UNDIRECTED) || + (params.getAdvertisingType() == GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED)) ? + PERIPHERAL_NON_CONNECTABLE : + PERIPHERAL_CONNECTABLE; + pal::own_address_type_t own_address_type = get_own_address_type(address_use_type); if(_privacy_enabled && (own_address_type == pal::own_address_type_t::RANDOM_ADDRESS)) @@ -1024,11 +1055,13 @@ ble_error_t GenericGap::reset(void) void GenericGap::processConnectionEvent( Handle_t handle, Role_t role, - BLEProtocol::AddressType_t peerAddrType, + PeerAddressType_t peerAddrType, const BLEProtocol::AddressBytes_t peerAddr, BLEProtocol::AddressType_t ownAddrType, const BLEProtocol::AddressBytes_t ownAddr, - const ConnectionParams_t *connectionParams + const ConnectionParams_t *connectionParams, + const uint8_t *peerResolvableAddr, + const uint8_t *localResolvableAddr ) { if (_connection_event_handler) { _connection_event_handler->on_connected( @@ -1049,7 +1082,9 @@ void GenericGap::processConnectionEvent( peerAddr, ownAddrType, ownAddr, - connectionParams + connectionParams, + peerResolvableAddr, + localResolvableAddr ); } @@ -1140,15 +1175,20 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) pal::GapAdvertisingReportEvent::advertising_t advertising = e[i]; // Check if the address hasn't been resolved - if(_privacy_enabled && _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER) - { - if(advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS) - { + if(_privacy_enabled && + _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER && + advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS && + is_random_private_resolvable_address(advertising.address.data()) + ) { // Filter it out - continue; - } + return; } + // note 1-to-1 conversion between connection_peer_address_type_t and + // peer_address_type_t + peer_address_type_t peer_address_type = + static_cast(advertising.address_type.value()); + processAdvertisementReport( advertising.address.data(), advertising.rssi, @@ -1156,96 +1196,105 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) (GapAdvertisingParams::AdvertisingType_t) advertising.type.value(), advertising.data.size(), advertising.data.data(), - (BLEProtocol::AddressType_t) advertising.address_type.value() + peer_address_type ); } } void GenericGap::on_connection_complete(const pal::GapConnectionCompleteEvent& e) { - // TODO: deprecate ownAddrType and ownAddr, those are not specified - // from the Bluetooth perspective - if (e.status == pal::hci_error_code_t::SUCCESS) { - bool needs_pairing = false; - bool needs_authentication = false; - - if(_privacy_enabled && (e.role.value() == e.role.SLAVE)) { - // Apply privacy policy if in peripheral mode for non-resolved addresses - RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); - ble_error_t ret = getRandomAddressType(e.peer_address.data(), &random_address_type); - if((ret != BLE_ERROR_NONE) - || (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE)) - { - switch(_peripheral_privacy_configuration.resolution_strategy) - { - case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: - // Reject connection request - the user will get notified through a callback - _pal_gap.disconnect(e.connection_handle, pal::disconnection_reason_t::AUTHENTICATION_FAILLURE); - return; - - case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: - needs_pairing = true; - break; - - case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: - needs_authentication = true; - break; - - default: - break; - } - } - } - - if (e.role.value() == e.role.SLAVE) { - _advertising_timeout.detach(); - _pal_gap.advertising_enable(false); - - // Stop address rotation if required - set_random_address_rotation(false); - } - - // using these parameters if stupid, there is no range for the - // connection interval when the connection is established - ConnectionParams_t connection_params = { - /* minConnectionInterval */ e.connection_interval, - /* maxConnectionInterval */ e.connection_interval, - e.connection_latency, - e.supervision_timeout - }; - ble::address_t address; - if (_address_type == BLEProtocol::AddressType::PUBLIC) { - address = _pal_gap.get_device_address(); - } else { - address = _pal_gap.get_random_address(); - } - - processConnectionEvent( - e.connection_handle, - e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, - (BLEProtocol::AddressType_t) e.peer_address_type.value(), - e.peer_address.data(), - _address_type, - address.data(), - &connection_params - ); - - // Now starts pairing or authentication procedures if required - if(needs_pairing) { - SecurityManager &sm = createBLEInstance()->getSecurityManager(); - // Request authentication to start pairing procedure - sm.requestAuthentication(e.connection_handle); - } - else if(needs_authentication) { - // TODO: GAP Authentication != Security Manager authentication - // Needs to be implemented - } - } else { + if (e.status != pal::hci_error_code_t::SUCCESS) { // for now notify user that the connection failled by issuing a timeout // event // TODO: Define events in case of connection faillure processTimeoutEvent(Gap::TIMEOUT_SRC_CONN); + return; + } + + bool needs_pairing = false; + bool needs_authentication = false; + + if (_privacy_enabled && + e.role.value() == e.role.SLAVE && + e.peer_address_type == peer_address_type_t::RANDOM + ) { + // Apply privacy policy if in peripheral mode for non-resolved addresses + RandomAddressType_t random_address_type(RandomAddressType_t::RESOLVABLE_PRIVATE); + ble_error_t err = getRandomAddressType(e.peer_address.data(), &random_address_type); + if (err) { + // FIXME: return for now; needs to report the error ? + return; + } + + if (random_address_type == RandomAddressType_t::RESOLVABLE_PRIVATE) { + switch(_peripheral_privacy_configuration.resolution_strategy) { + case PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS: + // Reject connection request - the user will get notified through a callback + _pal_gap.disconnect( + e.connection_handle, + pal::disconnection_reason_t::AUTHENTICATION_FAILLURE + ); + return; + + case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE: + needs_pairing = true; + break; + + case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE: + needs_authentication = true; + break; + + default: + break; + } + } + } + + if (e.role.value() == e.role.SLAVE) { + _advertising_timeout.detach(); + _pal_gap.advertising_enable(false); + + // Stop address rotation if required + set_random_address_rotation(false); + } + + // using these parameters if stupid, there is no range for the + // connection interval when the connection is established + ConnectionParams_t connection_params = { + /* minConnectionInterval */ e.connection_interval, + /* maxConnectionInterval */ e.connection_interval, + e.connection_latency, + e.supervision_timeout + }; + + ble::address_t address; + if (_address_type == LegacyAddressType::PUBLIC) { + address = _pal_gap.get_device_address(); + } else { + address = _pal_gap.get_random_address(); + } + + processConnectionEvent( + e.connection_handle, + e.role.value() == e.role.MASTER ? ::Gap::CENTRAL : ::Gap::PERIPHERAL, + e.peer_address_type, + e.peer_address.data(), + _address_type, + address.data(), + &connection_params, + e.local_resolvable_private_address.data(), + e.peer_resolvable_private_address.data() + ); + + // Now starts pairing or authentication procedures if required + if(needs_pairing) { + SecurityManager &sm = createBLEInstance()->getSecurityManager(); + // Request authentication to start pairing procedure + sm.requestAuthentication(e.connection_handle); + } else if(needs_authentication) { + // TODO: GAP Authentication != Security Manager authentication + // Needs to be implemented } } @@ -1431,7 +1480,7 @@ void GenericGap::update_random_address() return; } - _address_type = BLEProtocol::AddressType::RANDOM; + _address_type = LegacyAddressType::RANDOM_PRIVATE_NON_RESOLVABLE; _address = address; } From b973a8a490d7a37b06af35a63a1be81e4ac85d62 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 15:29:54 +0100 Subject: [PATCH 259/274] BLE: Add default constructor to peer_address_type_t --- features/FEATURE_BLE/ble/BLETypes.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/features/FEATURE_BLE/ble/BLETypes.h b/features/FEATURE_BLE/ble/BLETypes.h index 5a5b13fb22..7e57b17e2d 100644 --- a/features/FEATURE_BLE/ble/BLETypes.h +++ b/features/FEATURE_BLE/ble/BLETypes.h @@ -564,6 +564,12 @@ struct peer_address_type_t :SafeEnum { */ peer_address_type_t(type value) : SafeEnum(value) { } + + /** + * Default initialization of peer_address_type_t. + */ + peer_address_type_t() : + SafeEnum(PUBLIC) { } }; } // namespace ble From fb9e0dcbe74ad55bbb7998352aa2896282a10b13 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 21 May 2018 15:30:19 +0100 Subject: [PATCH 260/274] BLE: Fix resolvable private address identification. --- features/FEATURE_BLE/source/Gap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/Gap.cpp b/features/FEATURE_BLE/source/Gap.cpp index ca39bb645d..0ce6ebd62e 100644 --- a/features/FEATURE_BLE/source/Gap.cpp +++ b/features/FEATURE_BLE/source/Gap.cpp @@ -175,7 +175,7 @@ ble_error_t Gap::getRandomAddressType( case 0x00: *type = RandomAddressType_t::NON_RESOLVABLE_PRIVATE; return BLE_ERROR_NONE; - case 0x02: + case 0x01: *type = RandomAddressType_t::RESOLVABLE_PRIVATE; return BLE_ERROR_NONE; default: From 7d916a99979e559c2e2e478b4ea6692c4dcf9aaa Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 22 May 2018 11:45:38 +0100 Subject: [PATCH 261/274] fix not writing version number into the file --- .../source/generic/FileSecurityDb.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 7796a3d715..c2aa63474d 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -267,16 +267,15 @@ 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; - } + bool restore_toggle = false; + db_read(&restore_toggle, DB_OFFSET_RESTORE); + + if (!restore_toggle) { + erase_db_file(_db_file); + + db_write(&DB_VERSION, DB_OFFSET_VERSION); + return; } db_read(&_local_identity, DB_OFFSET_LOCAL_IDENTITY); From 1cd0c20fd087da09c2c0a661685c26e1b9a5223f Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 22 May 2018 12:11:07 +0100 Subject: [PATCH 262/274] fix opening the file in the wrong mode --- features/FEATURE_BLE/source/generic/FileSecurityDb.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index c2aa63474d..0f852fb83a 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -90,9 +90,16 @@ FILE* FileSecurityDb::open_db_file(const char *db_path) { return NULL; } - FILE *db_file = fopen(db_path, "wb+"); + /* try to open an existing file */ + FILE *db_file = fopen(db_path, "rb+"); if (!db_file) { + /* file doesn't exist, create it */ + db_file = fopen(db_path, "wb+"); + } + + if (!db_file) { + /* failed to create a file, abort */ return NULL; } From 84ff8311417a41a3bb287274927f468746adf87c Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 22 May 2018 12:25:11 +0100 Subject: [PATCH 263/274] measure file size with SEEK_END I thought that's not portable but the rest of the codebase uses it so no reason not to --- features/FEATURE_BLE/source/generic/FileSecurityDb.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 0f852fb83a..4d9fc7f4d0 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -112,10 +112,9 @@ FILE* FileSecurityDb::open_db_file(const char *db_path) { 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)) { + /* if file size differs from database size init the file */ + fseek(db_file, 0, SEEK_END); + if (ftell(db_file) != DB_SIZE) { init = true; } } else { From 08cb7aefd2d2b70f1ce1fe21074861c3adb39265 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 22 May 2018 14:08:09 +0100 Subject: [PATCH 264/274] fix not writing flags in the file flags kept with the rest of data for each entry --- .../source/generic/FileSecurityDb.cpp | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp index 4d9fc7f4d0..f8d1bfb6c9 100644 --- a/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp +++ b/features/FEATURE_BLE/source/generic/FileSecurityDb.cpp @@ -21,7 +21,8 @@ namespace generic { const uint16_t DB_VERSION = 1; -#define DB_STORE_OFFSET_LOCAL_KEYS (0) +#define DB_STORE_OFFSET_FLAGS (0) +#define DB_STORE_OFFSET_LOCAL_KEYS (DB_STORE_OFFSET_FLAGS + sizeof(SecurityDistributionFlags_t)) #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)) @@ -44,18 +45,13 @@ const uint16_t DB_VERSION = 1; #define PAD4(value) ((((value - 1) / 4) * 4) + 4) #define DB_SIZE_STORE \ - PAD4(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) + PAD4( \ + sizeof(SecurityDistributionFlags_t) + \ + sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryKeys_t) + \ + sizeof(SecurityEntryIdentity_t) + \ + sizeof(SecurityEntrySigning_t) \ + ) #define DB_SIZE_STORES \ (FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE) @@ -65,8 +61,7 @@ const uint16_t DB_VERSION = 1; #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_STORES (DB_OFFSET_LOCAL_SIGN_COUNT + sizeof(sign_count_t)) #define DB_OFFSET_MAX (DB_OFFSET_STORES + DB_SIZE_STORES) #define DB_SIZE PAD4(DB_OFFSET_MAX) @@ -288,10 +283,10 @@ void FileSecurityDb::restore() { 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*/ + /* read flags and sign counters */ for (size_t i = 0; i < get_entry_count(); i++) { - fread(&_entries[i], DB_SIZE_ENTRY, 1, _db_file); + db_read(&_entries[i].flags, _entries[i].file_offset + DB_STORE_OFFSET_FLAGS); + db_read(&_entries[i].peer_sign_counter, _entries[i].file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); } } @@ -303,6 +298,7 @@ void FileSecurityDb::sync(entry_handle_t db_handle) { } db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT); + db_write(&entry->flags, entry->file_offset + DB_STORE_OFFSET_FLAGS); } void FileSecurityDb::set_restore(bool reload) { From 69a0c10f00af42df872de5206ae58c1fa32b2f1a Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Tue, 22 May 2018 14:37:02 +0100 Subject: [PATCH 265/274] removing erroneous (and redundant) check this is gating on the wrong flag and the call doesn't require a check in the first place --- .../source/generic/GenericSecurityManager.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index 29adce2ba4..e2d5c8543d 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -1603,14 +1603,12 @@ void GenericSecurityManager::on_ltk_request( return; } - if (flags->ltk_stored) { - _db->get_entry_local_keys( - mbed::callback(this, &GenericSecurityManager::set_ltk_cb), - cb->db_entry, - ediv, - rand - ); - } + _db->get_entry_local_keys( + mbed::callback(this, &GenericSecurityManager::set_ltk_cb), + cb->db_entry, + ediv, + rand + ); } /* control blocks list management */ From d427fcfb59af61ea22ec4e6b3cee3e7b59af7134 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 22 May 2018 17:32:36 +0100 Subject: [PATCH 266/274] Nordic BLE: Remove dependency to mbedtls for CryptoToolbox::ah. --- .../TARGET_NRF51/source/nRF5xCrypto.cpp | 12 +++++++++--- .../TARGET_NRF51/source/nRF5xCrypto.h | 18 ++++++++++++++---- .../source/nRF5xPalSecurityManager.cpp | 5 ++--- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp index b555b0dc33..e6ff14a21b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.cpp @@ -32,6 +32,8 @@ #include "mbedtls/entropy.h" #include "mbedtls/ecp.h" +#endif + #include "platform/NonCopyable.h" #include "platform/CriticalSectionLock.h" #include "ble/BLETypes.h" @@ -46,6 +48,8 @@ namespace pal { namespace vendor { namespace nordic { +#if defined(MBEDTLS_ECDH_C) + CryptoToolbox::CryptoToolbox() : _initialized(false) { mbedtls_entropy_init(&_entropy_context); mbedtls_ecp_group_init(&_group); @@ -131,6 +135,8 @@ bool CryptoToolbox::generate_shared_secret( return err ? false : true; } +#endif + bool CryptoToolbox::ah( const ArrayView& irk, const ArrayView& prand, @@ -161,6 +167,7 @@ bool CryptoToolbox::ah( return true; } +#if defined(MBEDTLS_ECDH_C) void CryptoToolbox::load_mpi(mbedtls_mpi& dest, const ArrayView& src) { ble::public_key_coord_t src_be = src.data(); @@ -173,6 +180,8 @@ void CryptoToolbox::store_mpi(ArrayView& dest, const mb swap_endian(dest.data(), dest.size()); } +#endif + void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { for(size_t low = 0, high = (len - 1); high > low; --high, ++low) { std::swap(buf[low], buf[high]); @@ -183,6 +192,3 @@ void CryptoToolbox::swap_endian(uint8_t* buf, size_t len) { } // vendor } // pal } // ble - -#endif //defined(MBEDTLS_ECDH_C) - diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h index 35c56a875e..123fac3564 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xCrypto.h @@ -31,6 +31,8 @@ #include "mbedtls/entropy.h" #include "mbedtls/ecp.h" +#endif + #include "platform/NonCopyable.h" #include "ble/BLETypes.h" @@ -65,6 +67,8 @@ public: */ static const ptrdiff_t prand_size_ = 3; +#if defined(MBEDTLS_ECDH_C) + /** * Create a new CryptoToolbox. */ @@ -105,6 +109,8 @@ public: ArrayView shared_secret ); +#endif + /** * Execute the function ah. This function can be used to generate private * resolvable addresses and resolve them. @@ -118,22 +124,28 @@ public: * * @return true in case of success and false otherwise. */ - bool ah( + static bool ah( const ArrayView& irk, const ArrayView& prand, ArrayView hash ); private: + +#if defined(MBEDTLS_ECDH_C) void load_mpi(mbedtls_mpi& dest, const ArrayView& src); void store_mpi(ArrayView& dest, const mbedtls_mpi& src); +#endif - void swap_endian(uint8_t* buf, size_t len); + static void swap_endian(uint8_t* buf, size_t len); +#if defined(MBEDTLS_ECDH_C) bool _initialized; mbedtls_entropy_context _entropy_context; mbedtls_ecp_group _group; +#endif + }; } // nordic @@ -141,6 +153,4 @@ private: } // pal } // ble -#endif // defined(MBEDTLS_ECDH_C) - #endif // NRF5X_CRYPTO_ diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp index 287ce267b5..ba615211ac 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp @@ -213,7 +213,6 @@ nRF5xSecurityManager::get_resolving_list() { const nRF5xSecurityManager::resolving_list_entry_t* nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { -#if defined(MBEDTLS_ECDH_C) typedef byte_array_t hash_t; for (size_t i = 0; i < resolving_list_entry_count; ++i) { @@ -222,7 +221,7 @@ nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { // Compute the hash part from the random address part when the irk of // the entry is used - _crypto.ah( + CryptoToolbox::ah( make_const_ArrayView(entry.peer_irk), make_const_ArrayView( resolvable_address.data() + CryptoToolbox::hash_size_ @@ -237,7 +236,7 @@ nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) { return &entry; } } -#endif + return NULL; } From 755cf5fa5f862af868cb66ec813c893752596fd3 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 22 May 2018 17:37:57 +0100 Subject: [PATCH 267/274] BLE NRF51: Defer connection to a common function. The soft device is not consistent as it is required to force the connection to a resolved resolvable address so it should be known if the target is an identity address. --- .../TARGET_NRF51/source/nRF5xGap.cpp | 25 +++++++++++++++++-- .../TARGET_NRF51/source/nRF5xGap.h | 1 + 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp index d6dfb883cf..72edaa291b 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp @@ -458,7 +458,11 @@ ble_error_t nRF5xGap::connect( return BLE_ERROR_INVALID_PARAM; } - return connect(peerAddr, legacy_address, connectionParams, scanParamsIn); + bool identity = + peerAddrType == peer_address_type_t::PUBLIC_IDENTITY || + peerAddrType == peer_address_type_t::RANDOM_STATIC_IDENTITY; + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn, identity); } ble_error_t nRF5xGap::connect( @@ -466,6 +470,18 @@ ble_error_t nRF5xGap::connect( LegacyAddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParamsIn +) { + return connect(peerAddr, peerAddrType, connectionParams, scanParamsIn, /* identity */ false); +} + + + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn, + bool identity ) { ble_gap_addr_t addr; ble_gap_addr_t* addr_ptr = &addr; @@ -485,7 +501,7 @@ ble_error_t nRF5xGap::connect( connParams.conn_sup_timeout = 600; } - ble_gap_scan_params_t scanParams ={0}; + ble_gap_scan_params_t scanParams = { 0 }; #if (NRF_SD_BLE_API_VERSION <= 2) /* Allocate the stack's whitelist statically */ @@ -513,6 +529,11 @@ ble_error_t nRF5xGap::connect( whitelistIrkPtrs[i] = (ble_gap_irk_t*) entries[i].peer_irk.data(); } whitelist.irk_count = limit; + + if (identity) { + scanParams.selective = true; + addr_ptr = NULL; + } } set_private_resolvable_address(); diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h index d595de6278..a1f2700218 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h @@ -80,6 +80,7 @@ public: virtual ble_error_t stopAdvertising(void); virtual ble_error_t connect(const Address_t, ble::peer_address_type_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); + ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams, bool identity); virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); From ba61c09ffc432904444d57114fcf2fd3cd707775 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 22 May 2018 17:39:03 +0100 Subject: [PATCH 268/274] BLE NRF51: Resolve private address on connection in peripheral role Soft device inconsistency: The address is not resolved automatically if the device is a peripheral. --- .../TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp index 72edaa291b..6c01ae20ef 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp @@ -1248,6 +1248,16 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t #if (NRF_SD_BLE_API_VERSION <= 2) bool private_peer_known = evt.irk_match; + + // thanks to softdevice consistencies; addresses are not resolved on the + // peripheral side ... + if (_privacy_enabled && + evt.role == BLE_GAP_ROLE_PERIPH && + _peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE && + get_sm().resolve_address(evt.peer_addr.addr) != NULL + ) { + private_peer_known = true; + } #else bool private_peer_known = evt.peer_addr.addr_id_peer; #endif From cfe325cf0e5adf2ed0b248d65dedf24e0e149495 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 22 May 2018 17:40:18 +0100 Subject: [PATCH 269/274] BLE NRF51: Do not filter advertising packet in peripheral if the device as no bond. --- .../targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp index 6c01ae20ef..a80744df11 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp @@ -1352,7 +1352,9 @@ void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { if (entry) { peer_address = entry->peer_identity_address.data(); peer_addr_type = convert_identity_address(entry->peer_identity_address_type); - } else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) { + } else if (_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD || + get_sm().get_resolving_list().size() == 0 + ) { peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type); } else { // filter out the packet. From de41355c5c0b19d3a0d472fafefc88019e8345c5 Mon Sep 17 00:00:00 2001 From: paul-szczepanek-arm <33840200+paul-szczepanek-arm@users.noreply.github.com> Date: Wed, 23 May 2018 14:24:54 +0100 Subject: [PATCH 270/274] Fix not processing all advertising reports if one is filtered out filtering out individual reports instead of all --- features/FEATURE_BLE/source/generic/GenericGap.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/features/FEATURE_BLE/source/generic/GenericGap.cpp b/features/FEATURE_BLE/source/generic/GenericGap.cpp index 904e8caf9f..dc7e8c058a 100644 --- a/features/FEATURE_BLE/source/generic/GenericGap.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGap.cpp @@ -1180,8 +1180,8 @@ void GenericGap::on_advertising_report(const pal::GapAdvertisingReportEvent& e) advertising.address_type == pal::connection_peer_address_type_t::RANDOM_ADDRESS && is_random_private_resolvable_address(advertising.address.data()) ) { - // Filter it out - return; + // Filter it out + continue; } // note 1-to-1 conversion between connection_peer_address_type_t and From 1ba5a112f4dd61d9c3f03d0212530048f2f1794e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 May 2018 17:11:26 +0100 Subject: [PATCH 271/274] BLE: Fix wrong macro name for IAR --- features/FEATURE_BLE/source/BLE.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/source/BLE.cpp b/features/FEATURE_BLE/source/BLE.cpp index a78ec5861a..6e71eea6ad 100644 --- a/features/FEATURE_BLE/source/BLE.cpp +++ b/features/FEATURE_BLE/source/BLE.cpp @@ -50,7 +50,7 @@ #define BLE_DEPRECATED_API_USE_END \ _Pragma("pop") #else -#define BLE_DEPRECATED_API_USE_BEGIN +#define BLE_DEPRECATED_API_USE_END #endif static const char* error_strings[] = { From 30dac7cd8c694bdeaee0c596612259b3ef4a2966 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 May 2018 17:16:27 +0100 Subject: [PATCH 272/274] BLE NRF52: Fix identity address flag in connection request. --- .../TARGET_NRF52/source/nRF5xGap.cpp | 33 +++++++++++-------- .../TARGET_NRF52/source/nRF5xGap.h | 1 + 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index 7e72e35a22..ae6abae00e 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -501,7 +501,11 @@ ble_error_t nRF5xGap::connect( return BLE_ERROR_INVALID_PARAM; } - return connect(peerAddr, legacy_address, connectionParams, scanParamsIn); + bool identity = + peerAddrType == peer_address_type_t::PUBLIC_IDENTITY || + peerAddrType == peer_address_type_t::RANDOM_STATIC_IDENTITY; + + return connect(peerAddr, legacy_address, connectionParams, scanParamsIn, identity); } @@ -510,6 +514,16 @@ ble_error_t nRF5xGap::connect( LegacyAddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParamsIn +) { + return connect(peerAddr, peerAddrType, connectionParams, scanParamsIn, false); +} + +ble_error_t nRF5xGap::connect( + const Address_t peerAddr, + LegacyAddressType_t peerAddrType, + const ConnectionParams_t *connectionParams, + const GapScanningParams *scanParamsIn, + bool identity ) { ble_gap_addr_t addr; ble_gap_addr_t* addr_ptr = &addr; @@ -585,23 +599,16 @@ ble_error_t nRF5xGap::connect( scanParams.use_whitelist = (whitelistAddressesSize) ? 1 : 0; - if ((addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) - || (addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)) { - /* If a device is using Resolvable Private Addresses Section 1.3.2.2 (Core spec v4.2 volume 6 part B), - it shall also have an Identity Address that is either a Public or Random Static address type.” - To establish a connection, a static address must be provided by the application to the SoftDevice. - The SoftDevice resolves the address and connects to the right device if it is available. */ - addr.addr_id_peer = 1; - addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; - } else { - addr.addr_id_peer = 0; - } - if (_privacy_enabled) { bool enable_resolution = _central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE; update_identities_list(enable_resolution); + + if (enable_resolution && identity) { + addr.addr_id_peer = 1; + } + set_private_resolvable_address(); } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h index 27cabc9981..c8ef171ca4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.h @@ -88,6 +88,7 @@ public: virtual ble_error_t stopAdvertising(void); virtual ble_error_t connect(const Address_t, ble::peer_address_type_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); + ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams, bool identity); virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); virtual ble_error_t disconnect(DisconnectionReason_t reason); From ef208912a6ae58aa4b71f55f409fc6d5e8e1cf0f Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 May 2018 17:18:17 +0100 Subject: [PATCH 273/274] BLE NRF52: Report correct own address type for connection The function that gets the address doesn't work when privacy is enabled; report own address as private resolvable. --- .../targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index ae6abae00e..e2c76f2c05 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -1340,6 +1340,9 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t memcpy(own_address, evt.own_addr.addr, sizeof(own_address)); #else getAddress(&own_addr_type, own_address.data()); + if (_privacy_enabled) { + own_addr_type = LegacyAddressType::RANDOM_PRIVATE_RESOLVABLE; + } #endif #if (NRF_SD_BLE_API_VERSION <= 2) From db4d14c89d46fb64795e8c7501f04415d597bc0b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 May 2018 17:18:56 +0100 Subject: [PATCH 274/274] BLE NRF52: Fix advertising filtering when no bonds are present. --- .../targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp index e2c76f2c05..a5053b23f4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF52/source/nRF5xGap.cpp @@ -1432,7 +1432,9 @@ void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) { bool peer_address_resolved = evt.peer_addr.addr_id_peer; if (_privacy_enabled && - peer_address_resolved == false && + evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE && + peer_address_resolved == false && + get_sm().get_resolving_list().size() > 0 && _central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER ) { return;