From f7dfc5c9f223255a6663a05a3a35a914340c22da Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 3 Sep 2020 12:36:18 +0100 Subject: [PATCH 01/63] BLE: Update ble::Duration to support default values --- .../FEATURE_BLE/include/ble/common/Duration.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/common/Duration.h b/connectivity/FEATURE_BLE/include/ble/common/Duration.h index 4862ebb60f..30a962e523 100644 --- a/connectivity/FEATURE_BLE/include/ble/common/Duration.h +++ b/connectivity/FEATURE_BLE/include/ble/common/Duration.h @@ -33,10 +33,11 @@ namespace ble { * @tparam Min left-bound * @tparam Max right-bound */ -template +template struct Range { static const uint32_t MIN = Min; static const uint32_t MAX = Max; + static const uint32_t DEFAULT = Default; }; /** @@ -111,7 +112,7 @@ struct Duration { * * It is initialized with the minimum value acceptable. */ - Duration() : duration(Range::MIN) + Duration() : duration(Range::DEFAULT) { } @@ -598,11 +599,14 @@ bool operator>(Duration lhs, Duration rhs) #if !defined(DOXYGEN_ONLY) -template -const uint32_t Range::MIN; +template +const uint32_t Range::MIN; -template -const uint32_t Range::MAX; +template +const uint32_t Range::MAX; + +template +const uint32_t Range::DEFAULT; template const T Value::VALUE; From bc860db7c512ac7bf8bddcf88383303ab3e88844 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 3 Sep 2020 12:38:52 +0100 Subject: [PATCH 02/63] ble: Add privacy mode to the pal --- .../FEATURE_BLE/source/pal/GapTypes.h | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/pal/GapTypes.h b/connectivity/FEATURE_BLE/source/pal/GapTypes.h index 8248b4bdb5..c7a47b4868 100644 --- a/connectivity/FEATURE_BLE/source/pal/GapTypes.h +++ b/connectivity/FEATURE_BLE/source/pal/GapTypes.h @@ -652,6 +652,30 @@ struct direct_address_type_t : SafeEnum { typedef ble::clock_accuracy_t clock_accuracy_t; +/** + * Define the privacy mode of a peer. + */ +struct privacy_mode_t : SafeEnum { + enum type { + /** + * In Network mode, an observer or peripheral does not accept advertising + * packets containing the identity address of peer devices that have + * distributed their IRK + */ + NETWORK, + + /** + * In this mode, the device is only concerned about its own privacy. + * This mode should only be used when the Resolvable Private Address + * Only characteristic is not present in the GAP service of the peer + * device. + */ + DEVICE + }; + + privacy_mode_t(type value) : SafeEnum(value) {} +}; + } // namespace ble #endif /* BLE_PAL_GAP_TYPES_H_ */ From 742356158fc0f5f6a92a7b4847e486ddf0d9bf15 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 11:26:33 +0100 Subject: [PATCH 03/63] BLE: Add resolvable_address_timeout_t datatype. --- connectivity/FEATURE_BLE/include/ble/gap/Types.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/connectivity/FEATURE_BLE/include/ble/gap/Types.h b/connectivity/FEATURE_BLE/include/ble/gap/Types.h index 71b411124e..6049746940 100644 --- a/connectivity/FEATURE_BLE/include/ble/gap/Types.h +++ b/connectivity/FEATURE_BLE/include/ble/gap/Types.h @@ -121,6 +121,16 @@ typedef Duration > sync_timeout_t; */ typedef Duration > periodic_interval_t; +/** + * Resolvable address timeout. + * + * The duration is in seconds and ranges from 1 to 0xA1B8. The default value is + * 900 seconds. + */ +using resolvable_address_timeout_t = Duration< + uint16_t, second_t::TIME_BASE, Range<1, 0xA1B8, 0x0384> +>; + /** * Number of connection events that can be skipped by the slave. * From f1dbc893f3b43a72aeb8a82143a949d348faf168 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 16:37:53 +0100 Subject: [PATCH 04/63] BLE: Introduce PalPrivateAddressController This PAL interface is responsible for generating, resolving private address and maintaining the controller or host resolving list. It also indicates to upper level if LL resolution is supported or not and allows them to enable it. --- .../source/pal/PalPrivateAddressController.h | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h diff --git a/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h new file mode 100644 index 0000000000..4faa2545e1 --- /dev/null +++ b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h @@ -0,0 +1,246 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H +#define BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H + +#include "ble/common/BLETypes.h" +#include "ble/common/blecommon.h" +#include "GapTypes.h" + +namespace ble { + +/** + * Control the controller resolution list, resolve private addresses and generate + * new ones. + */ +struct PalPrivateAddressController { + struct EventHandler { + /** Called when the address resolution request has completed. + * + * @param success true if the address has been resolved and false otherwise. + */ + virtual void on_private_address_resolved(bool success) = 0; + + /** Called when the resolvable private address request has completed. + * + * @param rpa The address generated. In case of failure, the address is + * equal to an invalid address (default value from address_t). + */ + virtual void on_resolvable_private_address_generated(const address_t &rpa) = 0; + + /** + * Called when a new item has been added or removed to the resolving list + * or if the resolving list has been cleared. + */ + virtual void on_resolving_list_action_complete() = 0; + }; + + /** + * Initialize the address registry module + * @return BLE_ERROR_NONE in case of success. + */ + virtual ble_error_t initialize() = 0; + + /** + * Terminate the address registry module + * @return BLE_ERROR_NONE in case of success. + */ + virtual ble_error_t terminate() = 0; + + /** Generate a new resolvable private address from an IRK + * + * The completion of the request is signaled by the stack with a call to + * PalPrivateAddressController::on_resolvable_private_address_generated. + * + * @param local_irk The IRK to use to generate the address. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note Addresses are generated one at a time, this function should not be + * called while an address is being generated. + * + * @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.2 Private Device Address Generation + */ + virtual ble_error_t generate_resolvable_private_address(const irk_t& local_irk) = 0; + + /** Generate a new non-resolvable private address + * + * @return The address generated. + * + * @note The address generated might be invalid (all zeros). + * + * @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.2 Private Device Address Generation + */ + virtual address_t generate_non_resolvable_private_address() = 0; + + /** Attempt to resolve a resolvable private address received with an IRK. + * + * The completion of the request is signaled by the stack with a call to + * PalGapEventHandler::on_private_address_resolved. + * + * @param address The address to resole + * @param irk The IRK used for the resolution of the address. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note Addresses are resolved one at a time, this function should not be + * called while an address is being resolved. + * + * @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.3 Private Device Address Resolution + */ + virtual ble_error_t resolve_private_address( + const address_t &address, + const irk_t& irk + ) = 0; + + //////////////////////////////////////////////////////////////////////////// + // LL resolution and generation management + // + + /** Check if privacy feature is supported by LL implementation + * + * @return true if privacy is supported, false otherwise. + * + * @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature. + */ + virtual bool is_ll_privacy_supported() = 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. + */ + virtual ble_error_t set_ll_address_resolution( + bool enable + ) = 0; + + /** Set the timeout for LL resolvable private address rotation. + * + * @param timeout The timeout after which the resolvable private address in + * the controller is changed. + * + * @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.45 LE Set Resolvable Private Address Timeout Command + */ + virtual ble_error_t set_ll_resolvable_private_address_timeout(resolvable_address_timeout_t timeout) = 0; + + //////////////////////////////////////////////////////////////////////////// + // Resolving list management + // + + /** Return the resolving list capacity + * + * @return A positive number if LL privacy is supported, 0 if not. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.41 LE Read Resolving List Size Command. + */ + virtual uint8_t read_resolving_list_capacity() = 0; + + /** Add a device definition into the resolving list. + * + * @param peer_address_type The type of the identity address received from the + * peer during bonding. + * @param peer_identity_address The identity address of the peer received + * during bonding. + * @param peer_irk The irk of the peer. + * @param local_irk The irk sent to the peer during bonding. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: Cannot be used if address translation is enabled and the device is + * advertising/scanning or initiating. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.38 LE Add Device To Resolving List Command + */ + virtual ble_error_t add_device_to_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address, + const irk_t& peer_irk, + const irk_t& local_irk + ) = 0; + + /** Remove a device definition from the resolving list. + * + * @param peer_address_type The type of the identity address received from the + * peer during bonding. + * @param peer_identity_address The identity address of the peer received + * during bonding. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: Cannot be used if address translation is enabled and the device is + * advertising/scanning or initiating. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.39 LE Remove Device From Resolving List Command + */ + virtual ble_error_t remove_device_from_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address + ) = 0; + + /** Remove all entries from the resolving list. + * + * @return BLE_ERROR_NONE if the request has been successfully sent or the + * appropriate error otherwise. + * + * @note: Cannot be used if address translation is enabled and the device is + * advertising/scanning or initiating. + * + * @note: See Bluetooth 5 Vol 2 PartE: 7.8.40 LE Clear Resolving List Command + */ + virtual ble_error_t clear_resolving_list() = 0; + + /** Set the privacy mode (for LL controllers) + * + * @param peer_address_type The identity address type of the peer + * @param peer_address The identity address of the peer + * @param privacy_mode whether network or device privacy should be used for + * the peer. + * + * @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.77 LE Set Privacy Mode Command + */ + virtual ble_error_t set_peer_privacy_mode( + target_peer_address_type_t peer_address_type, + const address_t &peer_address, + privacy_mode_t privacy_mode + ) = 0; + + /** + * Set the event handler receiving events from this instance. + * @param handler The handler to use when an event happen. + */ + virtual void set_event_handler(EventHandler *handler) = 0; +}; + +} // namespace ble + + +#endif //BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H From 7dacae73b2351ff1a6679422ace575d9441980c4 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 16:48:19 +0100 Subject: [PATCH 05/63] BLE: Add cordio implementation of PalPrivateAddressController --- .../PalPrivateAddressControllerImpl.cpp | 227 ++++++++++++++++++ .../source/PalPrivateAddressControllerImpl.h | 94 ++++++++ 2 files changed, 321 insertions(+) create mode 100644 connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp create mode 100644 connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp new file mode 100644 index 0000000000..2bc49b2ad7 --- /dev/null +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp @@ -0,0 +1,227 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "PalPrivateAddressControllerImpl.h" +#include "dm_api.h" + +namespace ble { +namespace impl { + +ble_error_t PalPrivateAddressController::initialize() +{ + DmPrivInit(); + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::terminate() +{ + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::generate_resolvable_private_address(const irk_t& local_irk) +{ + if (_generating_rpa) { + return BLE_ERROR_INVALID_STATE; + } + + DmPrivGenerateAddr(const_cast(local_irk.data()), 0); + _generating_rpa = true; + return BLE_ERROR_NONE; +} + +address_t PalPrivateAddressController::generate_non_resolvable_private_address() +{ + address_t address; + SecRand(address.data(), address.size()); + DM_RAND_ADDR_SET(address, DM_RAND_ADDR_NONRESOLV); + return address; +} + +ble_error_t PalPrivateAddressController::resolve_private_address( + const address_t &address, + const irk_t& irk +) +{ + if (_resolving_rpa) { + return BLE_ERROR_INVALID_STATE; + } + + DmPrivResolveAddr( + const_cast(address.data()), + const_cast(irk.data()), + 0 + ); + return BLE_ERROR_NONE; +} + +bool PalPrivateAddressController::is_ll_privacy_supported() +{ + return HciLlPrivacySupported(); +} + +ble_error_t PalPrivateAddressController::set_ll_address_resolution(bool enable) +{ + DmPrivSetAddrResEnable(enable); + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::set_ll_resolvable_private_address_timeout( + resolvable_address_timeout_t timeout +) +{ + if (HciLlPrivacySupported() == false) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + DmPrivSetResolvablePrivateAddrTimeout(timeout.value()); + return BLE_ERROR_NONE; +} + +uint8_t PalPrivateAddressController::read_resolving_list_capacity() +{ + return HciGetResolvingListSize(); +} + +ble_error_t PalPrivateAddressController::add_device_to_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address, + const irk_t& peer_irk, + const irk_t& local_irk +) +{ + if (is_ll_privacy_supported() == false) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + DmPrivAddDevToResList( + peer_address_type.value(), + peer_identity_address.data(), + const_cast(peer_irk.data()), + const_cast(local_irk.data()), + true, + 0 + ); + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::remove_device_from_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address +) +{ + if (is_ll_privacy_supported() == false) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + DmPrivRemDevFromResList(peer_address_type.value(), peer_identity_address.data(), 0); + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::set_peer_privacy_mode( + target_peer_address_type_t peer_address_type, + const address_t &peer_address, + privacy_mode_t privacy_mode +) +{ + if (is_ll_privacy_supported() == false) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + DmPrivSetPrivacyMode( + peer_address_type.value(), + peer_address.data(), + privacy_mode.value() + ); + return BLE_ERROR_NONE; +} + +ble_error_t PalPrivateAddressController::clear_resolving_list() +{ + if (is_ll_privacy_supported() == false) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + DmPrivClearResList(); + return BLE_ERROR_NONE; +} + +void PalPrivateAddressController::set_event_handler(EventHandler *handler) +{ + _event_handler = handler; +} + +PalPrivateAddressController& PalPrivateAddressController::instance() +{ + static impl::PalPrivateAddressController self; + return self; +} + +bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg) +{ + if (msg == nullptr) { + return false; + } + + auto* handler = instance()._event_handler; + + switch (msg->event) { + case DM_PRIV_GENERATE_ADDR_IND: { + instance()._generating_rpa = false; + + if (!handler) { + return true; + } + + const auto *evt = (const dmPrivGenAddrIndEvt_t*) msg; + if (evt->hdr.status == HCI_SUCCESS) { + handler->on_resolvable_private_address_generated(evt->addr); + } else { + handler->on_resolvable_private_address_generated(address_t{}); + } + return true; + } + + case DM_PRIV_RESOLVED_ADDR_IND: { + instance()._resolving_rpa = false; + + if (!handler) { + return true; + } + + handler->on_private_address_resolved(msg->status == HCI_SUCCESS); + return true; + } + + 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 + { + if (!handler) { + return true; + } + + // Previous command completed, we can move to the next control block + handler->on_resolving_list_action_complete(); + return true; + } + + default: + return false; + } +} + +} // namespace impl +} // namespace ble + diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h new file mode 100644 index 0000000000..6076f8cbee --- /dev/null +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h @@ -0,0 +1,94 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H +#define BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H + +#include "source/pal/PalPrivateAddressController.h" +#include "dm_api.h" + +namespace ble { +namespace impl { + +/** + * Cordio implementation of a ble::PalPrivateAddressController. + */ +struct PalPrivateAddressController final : public ble::PalPrivateAddressController { + + ble_error_t initialize() final; + + ble_error_t terminate() final; + + ble_error_t generate_resolvable_private_address(const irk_t& local_irk) final; + + address_t generate_non_resolvable_private_address() final; + + ble_error_t resolve_private_address( + const address_t &address, + const irk_t& irk + ) final; + + bool is_ll_privacy_supported() final; + + ble_error_t set_ll_address_resolution(bool enable) final; + + ble_error_t set_ll_resolvable_private_address_timeout(resolvable_address_timeout_t timeout) final; + + uint8_t read_resolving_list_capacity() final; + + ble_error_t add_device_to_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address, + const irk_t& peer_irk, + const irk_t& local_irk + ) final; + + ble_error_t remove_device_from_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address + ) final; + + ble_error_t clear_resolving_list() final; + + ble_error_t set_peer_privacy_mode( + target_peer_address_type_t peer_address_type, + const address_t &peer_address, + privacy_mode_t privacy_mode + ) final; + + void set_event_handler(EventHandler *handler) final; + + static PalPrivateAddressController& instance(); + + /** + * Callback which handle wsfMsgHdr_t and forward them to emit_gap_event. + */ + static bool cordio_handler(const wsfMsgHdr_t *msg); + +private: + PalPrivateAddressController() = default; + + EventHandler *_event_handler = nullptr; + bool _generating_rpa = false; + bool _resolving_rpa = false; +}; + + +} // namespace impl +} // namespace ble + +#endif //BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H From 44681ee98250094f68f6b998ede0b923156a318b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 17:33:34 +0100 Subject: [PATCH 06/63] BLE: Add PrivateAddressController module. It controls private address generation and host or controller address resolution. --- .../generic/PrivateAddressController.cpp | 670 ++++++++++++++++++ .../source/generic/PrivateAddressController.h | 307 ++++++++ 2 files changed, 977 insertions(+) create mode 100644 connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp create mode 100644 connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp new file mode 100644 index 0000000000..f9fa503410 --- /dev/null +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -0,0 +1,670 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "PrivateAddressController.h" + +namespace ble { + +PrivateAddressController::PrivateAddressController( + PalPrivateAddressController &address_generator, + PalEventQueue &event_queue, + ble::resolvable_address_timeout_t rotation_timeout +) : + _pal(address_generator) , + _event_queue(event_queue), + _rotation_timeout(rotation_timeout) +{ + _pal.initialize(); + _pal.set_event_handler(this); + + auto** next = &_free_resolution_entries; + for (auto &entry : _resolution_list) { + *next = &entry; + next = &entry.next; + } +} + +PrivateAddressController::~PrivateAddressController() +{ + clear_privacy_control_blocks(); + _pal.terminate(); +} + +void PrivateAddressController::set_local_irk(const irk_t &local_irk) +{ + _local_irk = local_irk; + generate_resolvable_address(); +} + +void PrivateAddressController::set_timeout(ble::resolvable_address_timeout_t rotation_timeout) +{ + _rotation_timeout = rotation_timeout; + _pal.set_ll_resolvable_private_address_timeout(rotation_timeout); + if (_generation_started) { + stop_private_address_generation(); + start_private_address_generation(); + } +} + +const address_t& PrivateAddressController::get_resolvable_private_address() +{ + return _resolvable_address; +} + +const address_t& PrivateAddressController::get_non_resolvable_private_address() +{ + return _non_resolvable_address; +} + +void PrivateAddressController::set_event_handler(EventHandler *handler) +{ + _event_handler = handler; +} + +void PrivateAddressController::start_private_address_generation() +{ + if (_generation_started) { + return; + } + + // non resolvable private address generation has been delayed until now, + // generate it. + generate_non_resolvable_address(); + + _address_rotation_ticker.attach([this] { + _event_queue.post([this]{ + generate_resolvable_address(); + generate_non_resolvable_address(); + }); + }, _rotation_timeout.valueChrono()); + _generation_started = true; +} + +void PrivateAddressController::stop_private_address_generation() +{ + if (_generation_started) { + _address_rotation_ticker.detach(); + _generation_started = false; + } +} + +void PrivateAddressController::generate_resolvable_address() +{ + if (_local_irk != irk_t{}) { + _pal.generate_resolvable_private_address(_local_irk); + } +} + +void PrivateAddressController::on_resolvable_private_address_generated(const address_t &rpa) +{ + _resolvable_address = rpa; + if (_event_handler) { + _event_handler->on_resolvable_private_addresses_generated(_resolvable_address); + } +} + +void PrivateAddressController::generate_non_resolvable_address() +{ + _non_resolvable_address = _pal.generate_non_resolvable_private_address(); + _event_queue.post([this] { + if (_event_handler) { + _event_handler->on_non_resolvable_private_addresses_generated(_non_resolvable_address); + } + }); +} + +bool PrivateAddressController::is_controller_privacy_supported() +{ + return _pal.is_ll_privacy_supported(); +} + +ble_error_t PrivateAddressController::enable_controller_address_resolution(bool enable) +{ + MBED_ASSERT(is_controller_privacy_supported()); + return _pal.set_ll_address_resolution(enable); +} + +uint8_t PrivateAddressController::read_resolving_list_capacity() +{ + if (is_controller_privacy_supported()) { + return _pal.read_resolving_list_capacity(); + } else { + return RESOLVING_LIST_SIZE; + } +} + +ble_error_t PrivateAddressController::add_device_to_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address, + const irk_t& peer_irk +) +{ + if (_local_irk == irk_t{}) { + return BLE_ERROR_INVALID_STATE; + } + + if (is_controller_privacy_supported()) { + return queue_add_device_to_resolving_list( + peer_address_type, + peer_identity_address, + peer_irk + ); + } else { + for (auto &entry : _resolving_list) { + if (entry.populated == false) { + entry.peer_address_type = peer_address_type; + entry.peer_address = peer_identity_address; + entry.peer_irk = peer_irk; + entry.populated = true; + return BLE_ERROR_NONE; + } + } + + // Remove unresolved entries from the resolved list + remove_resolution_entry_from_cache( + [&](resolution_entry_t &entry) { + return entry.identity == nullptr; + } + ); + + // reset pending resolution request + restart_resolution_process(); + + return BLE_ERROR_NO_MEM; + } +} + +ble_error_t PrivateAddressController::remove_device_from_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address +) +{ + if (is_controller_privacy_supported()) { + return queue_remove_device_from_resolving_list(peer_address_type, peer_identity_address); + } else { + for (auto &entry : _resolving_list) { + if (entry.populated && + entry.peer_address_type == peer_address_type && + entry.peer_address == peer_identity_address + ) { + remove_resolution_entry_from_cache([&](resolution_entry_t& cache_entry) { + return cache_entry.identity == &entry; + }); + + entry.populated = false; + + restart_resolution_process(); + } + } + return BLE_ERROR_NONE; + } +} + +ble_error_t PrivateAddressController::clear_resolving_list() +{ + if (is_controller_privacy_supported()) { + return queue_clear_resolving_list(); + } else { + // Remove entry from the resolving list + for (auto &entry : _resolving_list) { + entry.populated = false; + } + // Remove all resolved entries from the cache + remove_resolution_entry_from_cache([&](resolution_entry_t& entry) { + return entry.identity != nullptr; + }); + + restart_resolution_process(); + + return BLE_ERROR_NONE; + } +} + +ble_error_t PrivateAddressController::resolve_address( + const address_t &peer_address, + bool *resolution_complete, + target_peer_address_type_t *retrieved_address_type, + const address_t **retrieved_address +) +{ + if (is_controller_privacy_supported()) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + // An LRU cache is used, we first traverse the list of resolved address + // and return any match + auto *entry = _resolved_list; + decltype(entry) previous = nullptr; + while (entry) { + if (entry->address == peer_address) { + *resolution_complete = true; + // The list contains resolved addresses AND unresolved addresses. + // Fill input parameters accordingly + if (entry->identity) { + *retrieved_address = &entry->identity->peer_address; + *retrieved_address_type = entry->identity->peer_address_type; + } else { + *retrieved_address = nullptr; + } + // update cache if we're not at the first entry + if (previous) { + previous->next = entry->next; + entry->next = _resolved_list; + _resolved_list = entry; + } + return BLE_ERROR_NONE; + } + previous = entry; + entry = entry->next; + } + + // In the case the address has not been resolved, we start the resolution + // process. + *resolution_complete = false; + return queue_resolve_address(peer_address); +} + +void PrivateAddressController::on_resolving_list_action_complete() +{ + process_privacy_control_blocks(true); +} + +struct PrivateAddressController::PrivacyControlBlock { + PrivacyControlBlock() : _next(nullptr) + { + } + + virtual ~PrivacyControlBlock() = default; + + // return trie if the handler has completed and false otherwise. + virtual bool execute(PrivateAddressController& self) = 0; + + void set_next(PrivacyControlBlock *next) + { + _next = next; + } + + PrivacyControlBlock *next() const + { + return _next; + } + +private: + PrivacyControlBlock *_next; +}; + +struct PrivateAddressController::PrivacyAddDevToResListControlBlock final : + PrivateAddressController::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) + { + } + + bool execute(PrivateAddressController& self) final + { + // Execute command + self._pal.add_device_to_resolving_list( + _peer_identity_address_type, + _peer_identity_address, + _peer_irk, + self._local_irk + ); + return false; + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; + irk_t _peer_irk; +}; + +ble_error_t PrivateAddressController::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 +) +{ + auto *cb = new(std::nothrow) PrivacyAddDevToResListControlBlock( + peer_identity_address_type, + peer_identity_address, + peer_irk + ); + if (cb == nullptr) { + // Cannot go further + return BLE_ERROR_NO_MEM; + } + + queue_privacy_control_block(cb); + + return BLE_ERROR_NONE; +} + +struct PrivateAddressController::PrivacyRemoveDevFromResListControlBlock final : + PrivateAddressController::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) + { + } + + bool execute(PrivateAddressController& self) final + { + // Execute command + self._pal.remove_device_from_resolving_list( + _peer_identity_address_type, + _peer_identity_address + ); + return false; + } + +private: + advertising_peer_address_type_t _peer_identity_address_type; + address_t _peer_identity_address; +}; + +ble_error_t PrivateAddressController::queue_remove_device_from_resolving_list( + advertising_peer_address_type_t peer_identity_address_type, + const address_t &peer_identity_address +) +{ + auto *cb = new(std::nothrow) PrivacyRemoveDevFromResListControlBlock( + peer_identity_address_type, + peer_identity_address + ); + if (cb == nullptr) { + // Cannot go further + return BLE_ERROR_NO_MEM; + } + + queue_privacy_control_block(cb); + return BLE_ERROR_NONE; +} + +struct PrivateAddressController::PrivacyClearResListControlBlock final : + PrivateAddressController::PrivacyControlBlock { + PrivacyClearResListControlBlock() : PrivacyControlBlock() + { + } + + bool execute(PrivateAddressController& self) final + { + // Execute command + self._pal.clear_resolving_list(); + return false; + } +}; + +ble_error_t PrivateAddressController::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(); + + auto *cb = new(std::nothrow) PrivacyClearResListControlBlock(); + if (cb == nullptr) { + // Cannot go further + return BLE_ERROR_NO_MEM; + } + + queue_privacy_control_block(cb); + return BLE_ERROR_NONE; +} + +struct PrivateAddressController::PrivacyResolveAddress final : + PrivateAddressController::PrivacyControlBlock { + PrivacyResolveAddress(const address_t &peer_address) : + PrivacyControlBlock(), + peer_address(peer_address) + { + } + + bool execute(PrivateAddressController& self) final + { + if (self._resolving_list[resolving_list_index].peer_irk == irk_t{}) { + // no entry at index 0, move to the next + return start_next_resolution_round(self); + } else { + // start the resolution process with the first entry on the list + start_resolution(self); + return false; + } + } + + bool on_resolution_complete(PrivateAddressController& self, bool resolved) + { + if (require_restart) { + require_restart = false; + resolving_list_index = 0; + return execute(self); + } else if (resolved) { + notify_completion( + self, peer_address, resolved, + &self._resolving_list[resolving_list_index] + ); + return true; + } else { + return start_next_resolution_round(self); + } + } + + void invalidate() { + require_restart = true; + } + +private: + bool start_next_resolution_round(PrivateAddressController& self) { + do { + ++resolving_list_index; + if (resolving_list_index == RESOLVING_LIST_SIZE) { + notify_completion(self, peer_address,false,nullptr); + return true; + } + } while (self._resolving_list[resolving_list_index].peer_irk != irk_t{}); + + start_resolution(self); + return false; + } + + void start_resolution(PrivateAddressController& self) { + self._pal.resolve_private_address( + peer_address, + self._resolving_list[resolving_list_index].peer_irk + ); + } + + void notify_completion( + PrivateAddressController& self, + const address_t &peer_resolvable_address, + bool resolved, + resolving_list_entry_t* identity + ) + { + // First we had the device to the resolution list + self.add_resolution_entry_to_cache(peer_resolvable_address, identity); + + if (!self._event_handler) { + return; + } + self._event_handler->on_address_resolution_completion( + peer_resolvable_address, + resolved, + identity ? identity->peer_address_type : target_peer_address_type_t::PUBLIC, + identity ? identity->peer_address : address_t{} + ); + } + + size_t resolving_list_index = 0; + address_t peer_address; + bool require_restart = false; +}; + +ble_error_t PrivateAddressController::queue_resolve_address(const address_t &peer_address) +{ + auto *cb = new(std::nothrow) PrivacyResolveAddress(peer_address); + if (cb == nullptr) { + // Cannot go further + return BLE_ERROR_NO_MEM; + } + + queue_privacy_control_block(cb); + return BLE_ERROR_NONE; +} + +void PrivateAddressController::restart_resolution_process() +{ + // if processing is active, restart the one running. + if (_processing_privacy_control_block && _pending_privacy_control_blocks) { + static_cast(_pending_privacy_control_blocks)->invalidate(); + } +} + +void PrivateAddressController::on_private_address_resolved(bool success) +{ + MBED_ASSERT(is_controller_privacy_supported() == false); + if (_pending_privacy_control_blocks == nullptr || + _processing_privacy_control_block == false + ) { + return; + } + + auto* cb = static_cast(_pending_privacy_control_blocks); + bool completed = cb->on_resolution_complete(*this, success); + process_privacy_control_blocks(completed); +} + +void PrivateAddressController::clear_privacy_control_blocks() +{ + while (_pending_privacy_control_blocks != nullptr) { + PrivacyControlBlock *next = _pending_privacy_control_blocks->next(); + delete _pending_privacy_control_blocks; + _pending_privacy_control_blocks = next; + } +} + +void PrivateAddressController::queue_privacy_control_block(PrivacyControlBlock *block) +{ + if (_pending_privacy_control_blocks == nullptr) { + _pending_privacy_control_blocks = block; + } else { + PrivacyControlBlock *node = _pending_privacy_control_blocks; + while (node->next() != nullptr) { + node = node->next(); + } + node->set_next(block); + } + + process_privacy_control_blocks(false); +} + +// If cb_completed is set to true, it means the previous control block has completed + +void PrivateAddressController::process_privacy_control_blocks(bool cb_completed) +{ + if ((_processing_privacy_control_block == true) && !cb_completed) { + // Busy, cannot process next control block for now + return; + } + + if (cb_completed && _pending_privacy_control_blocks) { + auto *next = _pending_privacy_control_blocks->next(); + delete _pending_privacy_control_blocks; + _pending_privacy_control_blocks = next; + } + + auto *cb = _pending_privacy_control_blocks; + if (cb == nullptr) { + // All control blocks processed + _processing_privacy_control_block = false; + return; + } + + while (cb) { + bool completed = cb->execute(*this); + if (completed) { + auto *next = cb->next(); + delete cb; + cb = next; + } else { + _processing_privacy_control_block = true; + break; + } + } + + _pending_privacy_control_blocks = cb; +} + +template +void PrivateAddressController::remove_resolution_entry_from_cache(const Pred &predicate) +{ + resolution_entry_t* previous = nullptr; + resolution_entry_t* entry = _resolved_list; + while (entry) { + if (predicate(*entry)) { + if (previous) { + previous->next = entry->next; + } else { + _resolved_list = entry->next; + } + entry->next = _free_resolution_entries; + _free_resolution_entries = entry; + if (previous) { + entry = previous->next; + } else { + entry = _resolved_list; + } + } else { + previous = entry; + entry = entry->next; + } + } +} + +void PrivateAddressController::add_resolution_entry_to_cache( + const address_t& address, resolving_list_entry_t* identity +) +{ + resolution_entry_t* entry = nullptr; + if (_free_resolution_entries) { + entry = _free_resolution_entries; + _free_resolution_entries = entry->next; + } else { + // retrieve the last entry in the resolved list + entry = _resolved_list; + resolution_entry_t *previous = nullptr; + while (entry->next) { + previous = entry; + entry = entry->next; + } + previous->next = nullptr; + } + + // Update the entry and insert it at the top of the list + entry->address = address; + entry->identity = identity; + entry->next = _resolved_list; + _resolved_list = entry; +} + +} // namespace ble \ No newline at end of file diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h new file mode 100644 index 0000000000..299be8d233 --- /dev/null +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -0,0 +1,307 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * 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 BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H +#define BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H + +#include + +#include "drivers/LowPowerTicker.h" +#include "ble/common/BLETypes.h" +#include "ble/common/blecommon.h" +#include "source/pal/PalEventQueue.h" +#include "source/pal/PalPrivateAddressController.h" + +namespace ble { + +/** + * This module generate resolvable and non resolvable private addresses usable + * by Gap when it advertise, scan or connect to a peer. + * It also manages the LL resolvable private address resolution and offer software + * workaround to resolve addresses on the host. + */ +class PrivateAddressController : private PalPrivateAddressController::EventHandler { +public: + struct EventHandler { + /** + * Called when a new resolvable private address has been generated. + * @param address The resolvable private address generated. + */ + virtual void on_resolvable_private_addresses_generated( + const address_t &address + ) = 0; + + /** + * Called when a new non resolvable private address has been generated. + * @param address The non resolvable private address generated. + */ + virtual void on_non_resolvable_private_addresses_generated( + const address_t &address + ) = 0; + + /** + * Called when address resolution has been completed by the host. + * + * @note Address resolution process is completly transparent when done + * in LL. + * + * @param peer_resolvable_address The resolvable address that was being + * resolved. + * @param resolved Indicate if the address has been resolved or not with + * local irks. If false, the params identity_address_type and + * identity_address are not valid. + * @param identity_address_type The type of the identity address resolved. + * @param identity_address The identity address resolved. + */ + virtual void on_address_resolution_completion( + const address_t &peer_resolvable_address, + bool resolved, + target_peer_address_type_t identity_address_type, + const address_t &identity_address + ) = 0; + }; + + /** + * Create a new PrivateAddressController. + * @param pal_address_controller Reference to the underlying pal. + * @param event_queue Reference to the event queue running in the stack + * context. + * @param rotation_timeout Time after which private addresses must be renew. + */ + PrivateAddressController( + PalPrivateAddressController &pal_address_controller, + PalEventQueue &event_queue, + ble::resolvable_address_timeout_t rotation_timeout + ); + + ~PrivateAddressController(); + + PrivateAddressController(const PrivateAddressController&) = delete; + PrivateAddressController& operator=(const PrivateAddressController&) = delete; + + /** + * Set the local irk used for address generation. Generation doesn't start + * until a valid irk has been set. + * @param local_irk + */ + void set_local_irk(const irk_t &local_irk); + + /** + * Change address renewal timeout. + * @param rotation_timeout address generation timeout. + */ + void set_timeout(ble::resolvable_address_timeout_t rotation_timeout); + + /** + * Get the current resolvable private address. + */ + const address_t& get_resolvable_private_address(); + + /** + * Get the current non resolvable private address. + */ + const address_t& get_non_resolvable_private_address(); + + /** + * Set the event handler catching events from this instance. + */ + void set_event_handler(EventHandler *handler); + + /** + * Start private address generation. A new address is generated when the + * timeout expired. + * it ends when stop_private_address_generation is called. + */ + void start_private_address_generation(); + + /** + * Stop private address generation. + */ + void stop_private_address_generation(); + + /** + * Return true if privacy is supported by the underlying controller and false + * otherwise. + */ + bool is_controller_privacy_supported(); + + /** + * Enable address resolution by the controller. + */ + ble_error_t enable_controller_address_resolution(bool enable); + + /** + * Read the number of entry that can be put in the resolving list. + */ + uint8_t read_resolving_list_capacity(); + + /** + * Add a new peer to the resolving list. + * @param peer_address_type The type of the peer's identity address. + * @param peer_identity_address The identity address of the peer. + * @param peer_irk The IRK of the peer. + * @return BLE_ERROR_NONE in case of success and false otherwise. + */ + ble_error_t add_device_to_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address, + const irk_t& peer_irk + ); + + /** + * Remove a device from the resolving list. + * @param peer_address_type The type of the peer's identity address. + * @param peer_identity_address The identity address of the peer. + * @return + */ + ble_error_t remove_device_from_resolving_list( + target_peer_address_type_t peer_address_type, + const address_t &peer_identity_address + ); + + /** + * Empty the resolving list. + */ + ble_error_t clear_resolving_list(); + + /** + * Resolve a private resolvable address on the host. + * + * To speedup operations, this module uses a cache to avoid too many + * resolutions. If the entry is available in the cache, it is returned + * immediately otherwise, the request will be completed by a report through + * EventHandler::on_address_resolution_completion + * + * @param peer_address the address to resolve. + * @param resolution_complete Set to true if the resolution process has been + * completed. If false, result will be made available by + * EventHandler::on_address_resolution_completion. + * @param retrieved_address_type The type of the address resolved. Valid if + * resolution_complete is equals to true AND retrieved_address is not null. + * @param retrieved_address If an entry has been found for the address in + * input this will be set to null if the address has not been resolved with + * the local irks or a pointer to the identity address if it has been resolved. + */ + ble_error_t resolve_address( + const address_t &peer_address, + bool *resolution_complete, + target_peer_address_type_t *retrieved_address_type, + const address_t **retrieved_address + ); + +private: + void generate_resolvable_address(); + + void generate_non_resolvable_address(); + + // EventHandler implementation + void on_resolvable_private_address_generated(const address_t &rpa) final; + + void on_private_address_resolved(bool success) final; + + void on_resolving_list_action_complete() final; + + // --- resolving list and resolution management + // The same list is shared between the two processes given they will never + // be active at the same time. Either the controller supports LL resolution + // and the list will only contain resolving list update operations or the + // controller doesn't support LL and address resolution is the only operation + // present in the operation list. + struct PrivacyControlBlock; + struct PrivacyClearResListControlBlock; + struct PrivacyAddDevToResListControlBlock; + struct PrivacyRemoveDevFromResListControlBlock; + + // Queue control block to add device to resolving list + ble_error_t 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 + ble_error_t 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 + ble_error_t queue_clear_resolving_list(); + + struct PrivacyResolveAddress; + ble_error_t queue_resolve_address(const address_t &peer_address); + + void restart_resolution_process(); + + // 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); + + template + void remove_resolution_entry_from_cache(const Pred& predicate); + + struct resolving_list_entry_t; + + void add_resolution_entry_to_cache(const address_t& address, resolving_list_entry_t* identity); + + PalPrivateAddressController &_pal; + PalEventQueue &_event_queue; + ble::resolvable_address_timeout_t _rotation_timeout; + bool _generation_started; + irk_t _local_irk = {}; + EventHandler *_event_handler = nullptr; + mbed::LowPowerTicker _address_rotation_ticker; + address_t _resolvable_address = {}; + address_t _non_resolvable_address = {}; + + PrivacyControlBlock *_pending_privacy_control_blocks = nullptr; + bool _processing_privacy_control_block = false; + + struct resolving_list_entry_t { + address_t peer_address = {}; + irk_t peer_irk = {}; + target_peer_address_type_t peer_address_type = target_peer_address_type_t::PUBLIC; + bool populated = false; + }; + + // FIXME: Use configuration + static const size_t RESOLVING_LIST_SIZE = 8; + resolving_list_entry_t _resolving_list[RESOLVING_LIST_SIZE]; + + + struct resolution_entry_t { + address_t address = address_t {}; + resolution_entry_t *next = nullptr; + resolving_list_entry_t *identity = nullptr; + }; + + // FIXME: Use configuration + static const size_t RESOLVED_ADDRESS_CACHE_SIZE = 16; + resolution_entry_t _resolution_list[RESOLVED_ADDRESS_CACHE_SIZE]; + resolution_entry_t *_resolved_list = nullptr; + resolution_entry_t *_free_resolution_entries = nullptr; +}; + +} + +#endif //BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H From 237278be241e781deb8f5fe595477353d9a307fe Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 17:42:42 +0100 Subject: [PATCH 07/63] BLE: Update security manager to use the PrivateAddressController Resolution list has been removed from the pal as this is handled by the PrivateAddressController. --- .../cordio/source/BLEInstanceBaseImpl.cpp | 22 +- .../cordio/source/BLEInstanceBaseImpl.h | 6 + .../cordio/source/PalSecurityManagerImpl.cpp | 274 ------------------ .../cordio/source/PalSecurityManagerImpl.h | 65 ----- .../source/generic/SecurityManagerImpl.cpp | 18 +- .../source/generic/SecurityManagerImpl.h | 7 +- .../source/pal/PalSecurityManager.h | 50 ---- 7 files changed, 43 insertions(+), 399 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp index 48df9f9b1c..f048ba01f6 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp @@ -285,7 +285,8 @@ ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl() static ble::impl::SecurityManager m_instance( ble::impl::PalSecurityManager::get_security_manager(), getGapImpl(), - signing_event_monitor + signing_event_monitor, + getPrivateAddressRegistry() ); return m_instance; @@ -303,6 +304,18 @@ const ble::SecurityManager &BLEInstanceBase::getSecurityManager() const return const_cast(self.getSecurityManager()); } +#if BLE_FEATURE_PRIVACY +ble::PrivateAddressController &BLEInstanceBase::getPrivateAddressRegistry() +{ + static ble::PrivateAddressController registry( + impl::PalPrivateAddressController::instance(), + _event_queue, + ble::resolvable_address_timeout_t{} + ); + return registry; +} +#endif + #endif // BLE_FEATURE_SECURITY void BLEInstanceBase::waitForEvent() @@ -337,6 +350,12 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg) if (ble::impl::PalSecurityManager::get_security_manager().sm_handler(msg)) { return; } + +#if BLE_FEATURE_PRIVACY + if (impl::PalPrivateAddressController::instance().cordio_handler(msg)) { + return; + } +#endif #endif // BLE_FEATURE_SECURITY switch (msg->event) { @@ -365,6 +384,7 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg) #if BLE_FEATURE_GATT_SERVER deviceInstance().getGattServerImpl().initialize(); #endif + deviceInstance().initialization_status = INITIALIZED; _init_callback.call(&context); } break; diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h index b91e9e30e0..ceb727a416 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.h @@ -42,6 +42,8 @@ #include "source/generic/SecurityManagerImpl.h" #include "source/GattServerImpl.h" #include "source/PalEventQueueImpl.h" +#include "source/PalPrivateAddressControllerImpl.h" +#include "source/generic/PrivateAddressController.h" #include "drivers/LowPowerTimer.h" @@ -157,6 +159,10 @@ public: */ const ble::SecurityManager &getSecurityManager() const final; +#if BLE_FEATURE_PRIVACY + ble::PrivateAddressController &getPrivateAddressRegistry(); +#endif + #endif // BLE_FEATURE_SECURITY /** diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp index 83094d06e9..772f7fa3a2 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp @@ -37,17 +37,12 @@ PalSecurityManager::PalSecurityManager() : _default_passkey(0), _lesc_keys_generated(false), _public_key_x(), - _pending_privacy_control_blocks(nullptr), - _processing_privacy_control_block(false), _peer_csrks() { } PalSecurityManager::~PalSecurityManager() { -#if BLE_FEATURE_PRIVACY - clear_privacy_control_blocks(); -#endif } //////////////////////////////////////////////////////////////////////////// @@ -93,68 +88,6 @@ ble_error_t PalSecurityManager::reset() return BLE_ERROR_NONE; } -//////////////////////////////////////////////////////////////////////////// -// Resolving list management -// - - -uint8_t PalSecurityManager::read_resolving_list_capacity() -{ - // 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 PalSecurityManager::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 (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 PalSecurityManager::remove_device_from_resolving_list( - advertising_peer_address_type_t peer_identity_address_type, - const address_t &peer_identity_address -) -{ - 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 PalSecurityManager::clear_resolving_list() -{ - 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; -} - //////////////////////////////////////////////////////////////////////////// // Feature support // @@ -841,220 +774,13 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg) return true; } -#if BLE_FEATURE_PRIVACY - // 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; - } -#endif // BLE_FEATURE_PRIVACY default: return false; } } - -struct PalSecurityManager::PrivacyControlBlock { - PrivacyControlBlock() : _next(nullptr) - { - } - - virtual ~PrivacyControlBlock() = default; - - virtual void execute() = 0; - - void set_next(PrivacyControlBlock *next) - { - _next = next; - } - - PrivacyControlBlock *next() const - { - return _next; - } - -private: - PrivacyControlBlock *_next; -}; - - -struct PalSecurityManager::PrivacyClearResListControlBlock final : PalSecurityManager::PrivacyControlBlock { - PrivacyClearResListControlBlock() : PrivacyControlBlock() - { - } - - void execute() final - { - // Execute command - DmPrivClearResList(); - } -}; - - -struct PalSecurityManager::PrivacyAddDevToResListControlBlock final : PalSecurityManager::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) - { - } - - void execute() final - { - // Execute command - DmPrivAddDevToResList( - _peer_identity_address_type.value(), - _peer_identity_address.data(), - _peer_irk.data(), - DmSecGetLocalIrk(), - false, - 0 - ); - } - -private: - advertising_peer_address_type_t _peer_identity_address_type; - address_t _peer_identity_address; - irk_t _peer_irk; -}; - - -struct PalSecurityManager::PrivacyRemoveDevFromResListControlBlock final : PalSecurityManager::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) - { - - } - - void execute() final - { - // 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 PalSecurityManager::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 -) -{ - auto *cb = new(std::nothrow) PrivacyAddDevToResListControlBlock( - peer_identity_address_type, - peer_identity_address, - peer_irk - ); - if (cb == nullptr) { - // Cannot go further - return; - } - - queue_privacy_control_block(cb); -} - - -void PalSecurityManager::queue_remove_device_from_resolving_list( - advertising_peer_address_type_t peer_identity_address_type, - const address_t &peer_identity_address -) -{ - auto *cb = new(std::nothrow) PrivacyRemoveDevFromResListControlBlock( - peer_identity_address_type, - peer_identity_address - ); - if (cb == nullptr) { - // Cannot go further - return; - } - - queue_privacy_control_block(cb); -} - - -void PalSecurityManager::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(); - - auto *cb = new(std::nothrow) PrivacyClearResListControlBlock(); - if (cb == nullptr) { - // Cannot go further - return; - } - - queue_privacy_control_block(cb); -} - - -void PalSecurityManager::clear_privacy_control_blocks() -{ - while (_pending_privacy_control_blocks != nullptr) { - PrivacyControlBlock *next = _pending_privacy_control_blocks->next(); - delete _pending_privacy_control_blocks; - _pending_privacy_control_blocks = next; - } -} - - -void PalSecurityManager::queue_privacy_control_block(PrivacyControlBlock *block) -{ - if (_pending_privacy_control_blocks == nullptr) { - _pending_privacy_control_blocks = block; - } else { - PrivacyControlBlock *node = _pending_privacy_control_blocks; - while (node->next() != nullptr) { - node = node->next(); - } - node->set_next(block); - } - - process_privacy_control_blocks(false); -} - -// If cb_completed is set to true, it means the previous control block has completed - -void PalSecurityManager::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 == nullptr) { - // 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; -} - - void PalSecurityManager::cleanup_peer_csrks() { for (auto & peer_csrk : _peer_csrks) { diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h index 95cca71034..ec955653f6 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h @@ -59,37 +59,6 @@ public: */ ble_error_t reset() final; - //////////////////////////////////////////////////////////////////////////// - // Resolving list management - // - - /** - * @see ::ble::PalSecurityManager::read_resolving_list_capacity - */ - uint8_t read_resolving_list_capacity() final; - - /** - * @see ::ble::PalSecurityManager::add_device_to_resolving_list - */ - 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 - ) final; - - /** - * @see ::ble::PalSecurityManager::remove_device_from_resolving_list - */ - ble_error_t remove_device_from_resolving_list( - advertising_peer_address_type_t peer_identity_address_type, - const address_t &peer_identity_address - ) final; - - /** - * @see ::ble::PalSecurityManager::clear_resolving_list - */ - ble_error_t clear_resolving_list() final; - //////////////////////////////////////////////////////////////////////////// // Pairing // @@ -347,37 +316,6 @@ public: private: - struct PrivacyControlBlock; - struct PrivacyClearResListControlBlock; - 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); - void cleanup_peer_csrks(); PalSecurityManagerEventHandler *_pal_event_handler; @@ -386,9 +324,6 @@ private: 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; irk_t _irk; csrk_t _csrk; csrk_t *_peer_csrks[DM_CONN_MAX]; diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index 75b4fabdfd..ef56f3f70d 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -134,9 +134,9 @@ ble_error_t SecurityManager::init( #if BLE_FEATURE_PRIVACY // set the local identity address and irk - if (result != BLE_ERROR_NONE) { + if (result == BLE_ERROR_NONE) { result = init_identity(); - } + } #endif // BLE_FEATURE_PRIVACY if (result != BLE_ERROR_NONE) { @@ -983,7 +983,7 @@ ble_error_t SecurityManager::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(); + uint8_t resolving_list_capacity = _private_address_controller.read_resolving_list_capacity(); auto* identity_list_p = new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity]; @@ -1051,7 +1051,11 @@ ble_error_t SecurityManager::init_identity() _db->set_local_identity(irk, identity_address, public_address); } - return _pal.set_irk(*pirk); + auto err = _pal.set_irk(*pirk); + if (!err) { + _private_address_controller.set_local_irk(*pirk); + } + return err; } @@ -1342,7 +1346,7 @@ void SecurityManager::on_security_entry_retrieved( typedef advertising_peer_address_type_t address_type_t; #if BLE_FEATURE_PRIVACY - _pal.add_device_to_resolving_list( + _private_address_controller.add_device_to_resolving_list( identity->identity_address_is_public ? address_type_t::PUBLIC : address_type_t::RANDOM, @@ -1360,9 +1364,9 @@ void SecurityManager::on_identity_list_retrieved( { typedef advertising_peer_address_type_t address_type_t; - _pal.clear_resolving_list(); + _private_address_controller.clear_resolving_list(); for (size_t i = 0; i < count; ++i) { - _pal.add_device_to_resolving_list( + _private_address_controller.add_device_to_resolving_list( identity_list[i].identity_address_is_public ? address_type_t::PUBLIC : address_type_t::RANDOM, diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h index d159880f89..576fd6ae92 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h @@ -37,7 +37,7 @@ #include "source/pal/PalSecurityManager.h" #include "source/generic/SecurityDb.h" - +#include "source/generic/PrivateAddressController.h" namespace ble { class PalGenericAccessService; @@ -451,12 +451,14 @@ public: SecurityManager( ble::PalSecurityManager &palImpl, ble::PalConnectionMonitor &connMonitorImpl, - ble::PalSigningMonitor &signingMonitorImpl + ble::PalSigningMonitor &signingMonitorImpl, + PrivateAddressController &privateAddressController ) : eventHandler(nullptr), _pal(palImpl), _connection_monitor(connMonitorImpl), _signing_monitor(signingMonitorImpl), _db(nullptr), + _private_address_controller(privateAddressController), _default_authentication(0), _default_key_distribution(KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), @@ -639,6 +641,7 @@ private: PalSigningMonitor &_signing_monitor; SecurityDb *_db; + PrivateAddressController &_private_address_controller; /* OOB data */ address_t _oob_local_address; diff --git a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h index 4a1906ee72..5a4e09cb8c 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h +++ b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h @@ -559,56 +559,6 @@ public: */ virtual ble_error_t reset() = 0; - //////////////////////////////////////////////////////////////////////////// - // Resolving list management - // - /** - * Return the number of address translation entries that can be stored by the - * subsystem. - * - * @warning: The number of entries is considered fixed. - * - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.41 - * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure - */ - virtual uint8_t read_resolving_list_capacity() = 0; - - /** - * Add a device definition into the resolving list of the LE subsystem. - * - * @param[in] peer_identity_address_type public/private indicator - * @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 - * @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, - const address_t &peer_identity_address, - const irk_t &peer_irk - ) = 0; - - /** - * Add a device definition from the resolving list of the LE subsystem. - * - * @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 - * @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, - const address_t &peer_identity_address - ) = 0; - - /** - * Remove all devices from the resolving list. - * - * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.40 - * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure - */ - virtual ble_error_t clear_resolving_list() = 0; - //////////////////////////////////////////////////////////////////////////// // Pairing // From 23f7a187fbc2ca2fb2264b76ac3b7509975d13ce Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 4 Sep 2020 17:45:34 +0100 Subject: [PATCH 08/63] BLE: Pal event queue pop before execution. A race condition was present if a single event was present in the event queue and the event was generating a new event. --- .../source/cordio/source/PalEventQueueImpl.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalEventQueueImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalEventQueueImpl.h index 507b7f09ea..e57c9e6679 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalEventQueueImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalEventQueueImpl.h @@ -116,11 +116,13 @@ public: void process() { while (_events) { - EventNode *next = _events->next; - _events->event(); - _events->~EventNode(); - WsfBufFree(_events); - _events = next; + // pop + auto *event = _events; + _events = event->next; + // execute and delete + event->event(); + event->~EventNode(); + WsfBufFree(event); } } From 313676a089241e9910b7af5af0599325e2c70d7d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 7 Sep 2020 09:19:27 +0100 Subject: [PATCH 09/63] BLE: Add gap handlers to be informed when advertising as started or been stopped --- .../source/cordio/source/PalGapImpl.cpp | 29 ++++++++++++++++--- .../FEATURE_BLE/source/generic/GapImpl.cpp | 11 +++++++ .../FEATURE_BLE/source/generic/GapImpl.h | 6 ++++ connectivity/FEATURE_BLE/source/pal/PalGap.h | 15 ++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index 07af679582..3cdeefc2e6 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -639,6 +639,20 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) break; #endif // BLE_FEATURE_PERIODIC_ADVERTISING + case DM_ADV_START_IND: + if (!handler) { + break; + } + handler->on_legacy_advertising_started(); + break; + + case DM_ADV_STOP_IND: + if (!handler) { + break; + } + handler->on_legacy_advertising_stopped(); + break; + #if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER case DM_SCAN_REQ_RCVD_IND: { if (!handler) { @@ -651,8 +665,16 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) connection_peer_address_type_t(evt->scanAddrType), evt->scanAddr ); - } - break; + } break; + + case DM_ADV_SET_START_IND: { + if (!handler) { + break; + } + const auto *evt = (const dmAdvSetStartEvt_t *) msg; + handler->on_advertising_set_started({evt->advHandle, evt->numSets}); + } break; + case DM_ADV_SET_STOP_IND: { const auto *evt = (const hciLeAdvSetTermEvt_t *) msg; @@ -676,8 +698,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) evt->handle, evt->numComplEvts ); - } - break; + } break; #endif // BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER #if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_OBSERVER diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 2a54487ed7..4b66e98efd 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2466,6 +2466,17 @@ void Gap::on_periodic_advertising_sync_loss(sync_handle_t sync_handle) ); } +void Gap::on_legacy_advertising_started() +{ +} + +void Gap::on_legacy_advertising_stopped() +{ +} + +void Gap::on_advertising_set_started(const mbed::Span& handles) +{ +} void Gap::on_advertising_set_terminated( hci_error_code_t status, diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 577292d2d6..0f29786f2e 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -494,6 +494,12 @@ private: void on_periodic_advertising_sync_loss(sync_handle_t sync_handle) override; + void on_legacy_advertising_started() override; + + void on_legacy_advertising_stopped() override; + + void on_advertising_set_started(const mbed::Span& handles) override; + void on_advertising_set_terminated( hci_error_code_t status, advertising_handle_t advertising_handle, diff --git a/connectivity/FEATURE_BLE/source/pal/PalGap.h b/connectivity/FEATURE_BLE/source/pal/PalGap.h index 53d6b28a8e..fd983b6a09 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGap.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGap.h @@ -198,6 +198,21 @@ public: */ virtual void on_scan_timeout( ) = 0; + /** + * Called when legacy advertising has been effectively started. + */ + virtual void on_legacy_advertising_started() = 0; + + /** + * Called when legacy advertising has been stopped. + */ + virtual void on_legacy_advertising_stopped() = 0; + + /** + * Called when extended advertising has been started. + */ + virtual void on_advertising_set_started(const mbed::Span& handles) = 0; + /** Called when advertising set stops advertising. * * @param status SUCCESS if connection has been established. From 7e16ee448e7bf027aa32e75e27c44f3621648d04 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 7 Sep 2020 09:30:18 +0100 Subject: [PATCH 10/63] BLE: Bind address controller with Gap --- .../cordio/source/BLEInstanceBaseImpl.cpp | 3 +- .../FEATURE_BLE/source/generic/GapImpl.cpp | 29 ++++++++++++++++++- .../FEATURE_BLE/source/generic/GapImpl.h | 23 +++++++++++++-- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp index f048ba01f6..e32fbeeb4d 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp @@ -201,7 +201,8 @@ ble::impl::Gap &BLEInstanceBase::getGapImpl() _event_queue, ble::impl::PalGap::get_gap(), cordio_gap_service, - ble::impl::PalSecurityManager::get_security_manager() + ble::impl::PalSecurityManager::get_security_manager(), + getPrivateAddressRegistry() ); return gap; } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 4b66e98efd..25dba4e2f2 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -319,11 +319,13 @@ Gap::Gap( ble::PalEventQueue &event_queue, ble::PalGap &pal_gap, ble::PalGenericAccessService &generic_access_service, - ble::PalSecurityManager &pal_sm + ble::PalSecurityManager &pal_sm, + ble::PrivateAddressController &pal_addr_reg ) : _event_queue(event_queue), _pal_gap(pal_gap), _gap_service(generic_access_service), _pal_sm(pal_sm), + _address_registry(pal_addr_reg), _address_type(own_address_type_t::PUBLIC), _initiator_policy_mode(initiator_policy_t::NO_FILTER), _scanning_filter_policy(scanning_filter_policy_t::NO_FILTER), @@ -348,6 +350,7 @@ Gap::Gap( _random_static_identity_address = _pal_gap.get_random_address(); _pal_gap.set_event_handler(this); + _address_registry.set_event_handler(this); } @@ -2893,5 +2896,29 @@ void Gap::setEventHandler(Gap::EventHandler *handler) _event_handler = handler; } + +void Gap::on_resolvable_private_addresses_generated(const address_t &address) +{ +} + +void Gap::on_non_resolvable_private_addresses_generated(const address_t &address) +{ +} + +void Gap::on_private_address_generated(bool connectable) +{ +} + + +void Gap::on_address_resolution_completion( + const address_t &peer_resolvable_address, + bool resolved, + target_peer_address_type_t identity_address_type, + const address_t &identity_address +) +{ + // FIXME: Implement +} +} } // impl } // ble diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 0f29786f2e..40b9be6752 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -38,6 +38,8 @@ #include "source/pal/PalGap.h" #include "source/pal/PalConnectionMonitor.h" +#include "source/pal/PalEventQueue.h" +#include "source/generic/PrivateAddressController.h" #include "ble/Gap.h" @@ -57,7 +59,8 @@ class BLEInstanceBase; class Gap : public ble::PalConnectionMonitor, - public PalGapEventHandler { + public PalGapEventHandler, + public PrivateAddressController::EventHandler { friend PalConnectionMonitor; friend PalGapEventHandler; friend PalGap; @@ -358,7 +361,8 @@ private: ble::PalEventQueue &event_queue, ble::PalGap &pal_gap, ble::PalGenericAccessService &generic_access_service, - ble::PalSecurityManager &pal_sm + ble::PalSecurityManager &pal_sm, + ble::PrivateAddressController &pal_addr_reg ); ~Gap(); @@ -533,6 +537,20 @@ private: void process_legacy_scan_timeout(); + /* Implement PrivateAddressController::EventHandler */ +private: + void on_resolvable_private_addresses_generated(const address_t &address) final; + + void on_non_resolvable_private_addresses_generated(const address_t &address) final; + + void on_private_address_generated(bool connectable); + + void on_address_resolution_completion( + const address_t &peer_resolvable_address, + bool resolved, + target_peer_address_type_t identity_address_type, + const address_t &identity_address + ) final; private: /** * Callchain containing all registered callback handlers for shutdown @@ -549,6 +567,7 @@ private: PalGap &_pal_gap; PalGenericAccessService &_gap_service; PalSecurityManager &_pal_sm; + PrivateAddressController &_address_registry; ble::own_address_type_t _address_type; ble::address_t _address; initiator_policy_t _initiator_policy_mode; From 13771b8172093b5b439e87fb069c10a9c709e2b5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 7 Sep 2020 09:55:52 +0100 Subject: [PATCH 11/63] BLE: Remove address resolution from GAP pal --- .../source/cordio/source/PalGapImpl.cpp | 18 ---------------- .../source/cordio/source/PalGapImpl.h | 6 ------ connectivity/FEATURE_BLE/source/pal/PalGap.h | 21 ------------------- 3 files changed, 45 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index 3cdeefc2e6..f7c7ba29a1 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -462,23 +462,6 @@ ble_error_t PalGap::disconnect( return BLE_ERROR_NONE; } - -bool PalGap::is_privacy_supported() -{ - // We only support controller-based privacy, so return whether the controller supports it - return HciLlPrivacySupported(); -} - - -ble_error_t PalGap::set_address_resolution( - bool enable -) -{ - DmPrivSetAddrResEnable(enable); - return BLE_ERROR_NONE; -} - - ble_error_t PalGap::read_phy(connection_handle_t connection) { if (is_feature_supported(controller_supported_features_t::LE_2M_PHY) @@ -489,7 +472,6 @@ ble_error_t PalGap::read_phy(connection_handle_t connection) return BLE_ERROR_NOT_IMPLEMENTED; } - ble_error_t PalGap::set_preferred_phys( const phy_set_t &tx_phys, const phy_set_t &rx_phys diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h index 50829fab5a..cc581ba0d1 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h @@ -147,12 +147,6 @@ public: local_disconnection_reason_t disconnection_reason ) final; - bool is_privacy_supported() final; - - ble_error_t set_address_resolution( - bool enable - ) final; - ble_error_t read_phy(connection_handle_t connection) final; ble_error_t set_preferred_phys( diff --git a/connectivity/FEATURE_BLE/source/pal/PalGap.h b/connectivity/FEATURE_BLE/source/pal/PalGap.h index fd983b6a09..425d561ab9 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGap.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGap.h @@ -1564,27 +1564,6 @@ public: local_disconnection_reason_t disconnection_reason ) = 0; - /** Check if privacy feature is supported by implementation - * - * @return true if privacy is supported, false otherwise. - * - * @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature. - */ - virtual bool is_privacy_supported() = 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. - */ - virtual ble_error_t set_address_resolution( - bool enable - ) = 0; - /** * Checked support for a feature in the link controller. * From f810ec4c2a878fc6ae2d75a401a2c356d9ea534c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 7 Sep 2020 10:02:41 +0100 Subject: [PATCH 12/63] BLE: Add initiating flag into gap to track if the local device tries to connect to a peer. --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 18 +++++++++++++++++- .../FEATURE_BLE/source/generic/GapImpl.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 25dba4e2f2..401bf554c5 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -646,7 +646,15 @@ ble_error_t Gap::rejectConnectionParametersUpdate( #if BLE_ROLE_CENTRAL ble_error_t Gap::cancelConnect() { - return _pal_gap.cancel_connection_creation(); + if (!_initiating) { + return BLE_ERROR_NONE; + } + + auto ret = _pal_gap.cancel_connection_creation(); + if (ret) { + _initiating = false; + } + return ret; } #endif @@ -1192,6 +1200,10 @@ void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) { + if (e.role == connection_role_t::CENTRAL) { + _initiating = false; + } + if (e.status != hci_error_code_t::SUCCESS) { if (_event_handler) { _event_handler->onConnectionComplete( @@ -2332,6 +2344,10 @@ void Gap::on_enhanced_connection_complete( return; } + if (own_role == connection_role_t::CENTRAL) { + _initiating = false; + } + _event_handler->onConnectionComplete( ConnectionCompleteEvent( (status == hci_error_code_t::SUCCESS) ? BLE_ERROR_NONE : BLE_ERROR_INTERNAL_STACK_FAILURE, diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 40b9be6752..0d9ccab86b 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -586,6 +586,7 @@ private: mbed::LowPowerTimeout _scan_timeout; mbed::LowPowerTicker _address_rotation_ticker; + bool _initiating = false; template struct BitArray { BitArray() : data() From 4b853956d9400ca20969fbf3fa63d132fae74eef Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Mon, 7 Sep 2020 10:12:20 +0100 Subject: [PATCH 13/63] BLE: Add resolvable and non resolvable private address rotation with advertising --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 509 +++++++++--------- .../FEATURE_BLE/source/generic/GapImpl.h | 31 +- 2 files changed, 287 insertions(+), 253 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 401bf554c5..c2866b23c2 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -302,6 +302,12 @@ microsecond_t minSupervisionTimeout( return (1 + slaveLatency.value()) * maxConnectionInterval * 2; } +bool is_connectable_advertising(const AdvertisingParameters ¶ms) +{ + advertising_event_properties_t event_properties(params.getType()); + return event_properties.connectable; +} + } // end of anonymous namespace const peripheral_privacy_configuration_t Gap::default_peripheral_privacy_configuration = { @@ -334,7 +340,6 @@ Gap::Gap( _privacy_enabled(false), _peripheral_privacy_configuration(default_peripheral_privacy_configuration), _central_privacy_configuration(default_central_privacy_configuration), - _random_address_rotating(false), _scan_enabled(false), _advertising_timeout(), _scan_timeout(), @@ -346,9 +351,6 @@ Gap::Gap( mbed::callback(this, &Gap::on_gap_event_received) ); - // Recover static random identity - _random_static_identity_address = _pal_gap.get_random_address(); - _pal_gap.set_event_handler(this); _address_registry.set_event_handler(this); } @@ -397,14 +399,17 @@ ble_error_t Gap::setRandomStaticAddress( return BLE_ERROR_INVALID_PARAM; } - ble_error_t err = _pal_gap.set_random_address(address); - if (err) { - return err; + if (!_privacy_enabled) { + ble_error_t err = _pal_gap.set_random_address(address); + if (err) { + return err; + } + + // FIXME: set random address for active sets + + _address_type = own_address_type_t::RANDOM; } - _address_type = own_address_type_t::RANDOM; - _address = address; - _random_static_identity_address = address; return BLE_ERROR_NONE; } @@ -471,11 +476,6 @@ ble_error_t Gap::stopScan() return err; } -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif - _scan_timeout.detach(); return BLE_ERROR_NONE; @@ -509,6 +509,8 @@ ble_error_t Gap::connect( } } + ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; + if (is_extended_advertising_available() == false) { phy_set_t set(connectionParams.getPhySet()); if (set.count() != 1 || set.get_1m() == false) { @@ -518,7 +520,7 @@ ble_error_t Gap::connect( // ensure scan is stopped. _pal_gap.scan_enable(false, false); - return _pal_gap.create_connection( + ret = _pal_gap.create_connection( connectionParams.getScanIntervalArray()[0], connectionParams.getScanWindowArray()[0], connectionParams.getFilter(), @@ -532,35 +534,39 @@ ble_error_t Gap::connect( connectionParams.getMinEventLengthArray()[0], connectionParams.getMaxConnectionIntervalArray()[0] ); + } else { + // ensure scan is stopped. + _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); + + // reduce the address type to public or random + peer_address_type_t adjusted_address_type(peer_address_type_t::PUBLIC); + + if (peerAddressType == peer_address_type_t::RANDOM || + peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY) { + adjusted_address_type = peer_address_type_t::RANDOM; + } + + ret = _pal_gap.extended_create_connection( + connectionParams.getFilter(), + connectionParams.getOwnAddressType(), + adjusted_address_type, + peerAddress, + connectionParams.getPhySet(), + connectionParams.getScanIntervalArray(), + connectionParams.getScanWindowArray(), + connectionParams.getMinConnectionIntervalArray(), + connectionParams.getMaxConnectionIntervalArray(), + connectionParams.getSlaveLatencyArray(), + connectionParams.getConnectionSupervisionTimeoutArray(), + connectionParams.getMinEventLengthArray(), + connectionParams.getMaxEventLengthArray() + ); } - // ensure scan is stopped. - _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); - - // reduce the address type to public or random - peer_address_type_t adjusted_address_type(peer_address_type_t::PUBLIC); - - if (peerAddressType == peer_address_type_t::RANDOM || - peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY - ) { - adjusted_address_type = peer_address_type_t::RANDOM; + if (ret == BLE_ERROR_NONE) { + _initiating = true; } - - return _pal_gap.extended_create_connection( - connectionParams.getFilter(), - connectionParams.getOwnAddressType(), - adjusted_address_type, - peerAddress, - connectionParams.getPhySet(), - connectionParams.getScanIntervalArray(), - connectionParams.getScanWindowArray(), - connectionParams.getMinConnectionIntervalArray(), - connectionParams.getMaxConnectionIntervalArray(), - connectionParams.getSlaveLatencyArray(), - connectionParams.getConnectionSupervisionTimeoutArray(), - connectionParams.getMinEventLengthArray(), - connectionParams.getMaxEventLengthArray() - ); + return ret; } #endif @@ -885,14 +891,21 @@ ble_error_t Gap::enablePrivacy(bool enable) return BLE_ERROR_NONE; } - if (enable && !_pal_gap.is_privacy_supported()) { - // Privacy is not supported by the implementation - return BLE_ERROR_NOT_IMPLEMENTED; + if (is_radio_active()) { + return BLE_ERROR_INVALID_STATE; } _privacy_enabled = enable; - update_address_resolution_setting(); + if (_privacy_enabled) { + _address_registry.start_private_address_generation(); + } else { + _address_registry.stop_private_address_generation(); + } + + if (_address_registry.is_controller_privacy_supported()) { + update_ll_address_resolution_setting(); + } return BLE_ERROR_NONE; } @@ -907,7 +920,7 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( { _peripheral_privacy_configuration = *configuration; - update_address_resolution_setting(); + update_ll_address_resolution_setting(); return BLE_ERROR_NONE; } @@ -937,7 +950,7 @@ ble_error_t Gap::setCentralPrivacyConfiguration( { _central_privacy_configuration = *configuration; - update_address_resolution_setting(); + update_ll_address_resolution_setting(); return BLE_ERROR_NONE; } @@ -1013,6 +1026,9 @@ ble_error_t Gap::reset() ); } _active_sets.clear(); + _pending_sets.clear(); + _address_refresh_sets.clear(); + _interruptible_sets.clear(); _connectable_payload_size_exceeded.clear(); _set_is_connectable.clear(); @@ -1065,9 +1081,7 @@ void Gap::process_legacy_scan_timeout() { /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); -#if BLE_FEATURE_PRIVACY - set_random_address_rotation(false); -#endif + _scan_enabled = false; if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); @@ -1083,16 +1097,11 @@ void Gap::on_advertising_timeout() void Gap::process_advertising_timeout() { - // This will signal timeout via onAdvertisingEnd() - ble_error_t err = _pal_gap.advertising_enable(false); - if (err) { - // TODO: define the mechanism signaling the error + if (!_active_sets.get(LEGACY_ADVERTISING_HANDLE)) { + return; } -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif + stopAdvertising(LEGACY_ADVERTISING_HANDLE); } @@ -1143,6 +1152,7 @@ void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) advertising.address_type == connection_peer_address_type_t::RANDOM_ADDRESS && is_random_private_resolvable_address(advertising.address.data()) ) { + // FIXME: implement // Filter it out continue; } @@ -1229,6 +1239,12 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) bool needs_pairing = false; bool needs_authentication = false; + // There is no need to check for extending advertising availability as this + // handler is for 4.x controllers + if (e.role == connection_role_t::PERIPHERAL) { + _active_sets.clear(LEGACY_ADVERTISING_HANDLE); + } + #if BLE_ROLE_PERIPHERAL #if BLE_FEATURE_PRIVACY if (_privacy_enabled && @@ -1271,11 +1287,6 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) if (e.role.value() == e.role.PERIPHERAL) { _advertising_timeout.detach(); _pal_gap.advertising_enable(false); - -#if BLE_FEATURE_PRIVACY - // Stop address rotation if required - set_random_address_rotation(false); -#endif } #endif // BLE_ROLE_PERIPHERAL @@ -1475,7 +1486,7 @@ bool Gap::initialize_whitelist() const } -ble_error_t Gap::update_address_resolution_setting() +ble_error_t Gap::update_ll_address_resolution_setting() { // enable if privacy is enabled and resolution is requested in either central or peripheral mode bool enable = false; @@ -1494,123 +1505,7 @@ ble_error_t Gap::update_address_resolution_setting() #endif // BLE_ROLE_OBSERVER } - return _pal_gap.set_address_resolution(enable); -} - - -void Gap::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( - mbed::callback(this, &Gap::on_address_rotation_timeout), - 15min - ); - } else { - // Stop ticker - _address_rotation_ticker.detach(); - - // Set static random identity address - _pal_gap.set_random_address( - _random_static_identity_address - ); - } -} - - -void Gap::update_random_address() -{ - if (!_random_address_rotating) { - // This event might have been queued before we disabled address rotation - return; - } -#if BLE_FEATURE_EXTENDED_ADVERTISING - if (is_extended_advertising_available()) { - for (uint8_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { - if (_existing_sets.get(i)) { - ble::address_t address; - - if (!getUnresolvableRandomAddress(address)) { - return; - } - - /* ignore the error, if it fails to cycle because it's connectable */ - _pal_gap.set_advertising_set_random_address( - (advertising_handle_t) i, - address - ); - } - } - } -#endif // BLE_FEATURE_EXTENDED_ADVERTISING - - ble::address_t address; - - if (!getUnresolvableRandomAddress(address)) { - return; - } - - ble_error_t err = _pal_gap.set_random_address( - address - ); - - if (err) { - return; - } - - _address_type = own_address_type_t::RANDOM; - _address = address; -} - - -bool Gap::getUnresolvableRandomAddress(ble::address_t &address) -{ - do { - byte_array_t<8> random_data; -#if BLE_FEATURE_SECURITY - ble_error_t ret = _pal_sm.get_random_data(random_data); -#else - ble_error_t ret = BLE_ERROR_NOT_IMPLEMENTED; -#endif // BLE_FEATURE_SECURITY - if (ret != BLE_ERROR_NONE) { - // Abort - return false; - } - - // 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); - - return true; -} - - -void Gap::on_address_rotation_timeout() -{ - _event_queue.post(mbed::callback(this, &Gap::update_random_address)); + return _address_registry.enable_controller_address_resolution(enable); } #if BLE_ROLE_BROADCASTER @@ -1671,18 +1566,22 @@ ble_error_t Gap::createAdvertisingSet( for (; new_handle < end; ++new_handle) { if (!_existing_sets.get(new_handle)) { - ble_error_t err = setExtendedAdvertisingParameters( + // Note: we use setAdvertisingParameters instead of + // setExtendedAdvertisingParameters as it checks all the inputs. + // We need to indicate the set existing before making the request + // in case of failure we mark it back as not existing. + _existing_sets.set(new_handle); + ble_error_t err = setAdvertisingParameters( new_handle, parameters ); + if (err) { - return err; + _existing_sets.clear(new_handle); + } else { + *handle = new_handle; } - - _existing_sets.set(new_handle); - *handle = new_handle; - - return BLE_ERROR_NONE; + return err; } } @@ -1712,7 +1611,7 @@ ble_error_t Gap::destroyAdvertisingSet(advertising_handle_t handle) return BLE_ERROR_INVALID_PARAM; } - if (_active_sets.get(handle)) { + if (_pending_sets.get(handle) || _active_sets.get(handle)) { return BLE_ERROR_OPERATION_NOT_PERMITTED; } #if BLE_FEATURE_PERIODIC_ADVERTISING @@ -1741,20 +1640,30 @@ ble_error_t Gap::setAdvertisingParameters( const AdvertisingParameters ¶ms ) { -#if BLE_FEATURE_EXTENDED_ADVERTISING if (handle >= getMaxAdvertisingSetNumber()) { return BLE_ERROR_INVALID_PARAM; } + // It is not permited to reconfigure an advertising set while advertising + if (_pending_sets.get(handle) || _active_sets.get(handle)) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } + +#if BLE_FEATURE_PRIVACY + // If privacy is enabled, alter the own address type used during advertising + if (_privacy_enabled && params.getOwnAddressType() != own_address_type_t::RANDOM) { + return BLE_ERROR_INVALID_PARAM; + } +#endif + +#if BLE_FEATURE_EXTENDED_ADVERTISING if (!_existing_sets.get(handle)) { if (handle == LEGACY_ADVERTISING_HANDLE) { - prepare_legacy_advertising_set(); + return prepare_legacy_advertising_set(params); } else { return BLE_ERROR_INVALID_PARAM; } - } - - if (is_extended_advertising_available()) { + } else if (is_extended_advertising_available()) { return setExtendedAdvertisingParameters(handle, params); } else #endif // BLE_FEATURE_EXTENDED_ADVERTISING @@ -1769,7 +1678,7 @@ ble_error_t Gap::setAdvertisingParameters( params.getChannel39() ); - return _pal_gap.set_advertising_parameters( + auto err = _pal_gap.set_advertising_parameters( params.getMinPrimaryInterval().value(), params.getMaxPrimaryInterval().value(), params.getType(), @@ -1779,30 +1688,25 @@ ble_error_t Gap::setAdvertisingParameters( channel_map, params.getFilter() ); + + if (!err) { + update_advertising_set_connectable_attribute(handle, params); + } + return err; } } #endif - ble_error_t Gap::setExtendedAdvertisingParameters( advertising_handle_t handle, const AdvertisingParameters ¶ms ) { - if (handle >= getMaxAdvertisingSetNumber()) { - return BLE_ERROR_INVALID_PARAM; - } - - if (_active_sets.get(handle)) { - return BLE_ERROR_OPERATION_NOT_PERMITTED; - } - /* check for illegal parameter combination */ - if (( - params.getType() == advertising_type_t::CONNECTABLE_UNDIRECTED || - params.getType() == advertising_type_t::CONNECTABLE_DIRECTED - ) && - params.getUseLegacyPDU() == false) { + if ((params.getType() == advertising_type_t::CONNECTABLE_UNDIRECTED || + params.getType() == advertising_type_t::CONNECTABLE_DIRECTED) && + params.getUseLegacyPDU() == false + ) { /* these types can only be used with legacy PDUs */ return BLE_ERROR_INVALID_PARAM; } @@ -1818,7 +1722,7 @@ ble_error_t Gap::setExtendedAdvertisingParameters( params.getChannel39() ); - ble_error_t err = _pal_gap.set_extended_advertising_parameters( + auto err = _pal_gap.set_extended_advertising_parameters( handle, event_properties, params.getMinPrimaryInterval().value(), @@ -1836,20 +1740,11 @@ ble_error_t Gap::setExtendedAdvertisingParameters( params.getScanRequestNotification() ); - if (err) { - return err; + if (!err) { + update_advertising_set_connectable_attribute(handle, params); } - if (event_properties.connectable) { - _set_is_connectable.set(handle); - } else { - _set_is_connectable.clear(handle); - } - - return _pal_gap.set_advertising_set_random_address( - handle, - _random_static_identity_address - ); + return err; } @@ -1913,7 +1808,7 @@ ble_error_t Gap::setAdvertisingData( if (!_existing_sets.get(handle)) { if (handle == LEGACY_ADVERTISING_HANDLE) { - prepare_legacy_advertising_set(); + prepare_legacy_advertising_set(AdvertisingParameters{}); } else { return BLE_ERROR_INVALID_PARAM; } @@ -1948,7 +1843,7 @@ ble_error_t Gap::setAdvertisingData( return BLE_ERROR_INVALID_PARAM; } - if (!_active_sets.get(handle) && payload.size() > this->getMaxActiveSetAdvertisingDataLength()) { + if ((_pending_sets.get(handle) || _active_sets.get(handle)) && payload.size() > this->getMaxActiveSetAdvertisingDataLength()) { MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for active sets needs to fit in a single operation" " - not greater than getMaxActiveSetAdvertisingDataLength()."); return BLE_ERROR_INVALID_PARAM; @@ -1956,7 +1851,7 @@ ble_error_t Gap::setAdvertisingData( if (!scan_response) { if (payload.size() > this->getMaxConnectableAdvertisingDataLength()) { - if (_active_sets.get(handle) && _set_is_connectable.get(handle)) { + if ((_pending_sets.get(handle) || _active_sets.get(handle)) && _set_is_connectable.get(handle)) { MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size for connectable advertising" " exceeds getMaxAdvertisingDataLength()."); return BLE_ERROR_INVALID_PARAM; @@ -2019,6 +1914,11 @@ ble_error_t Gap::startAdvertising( { ble_error_t error = BLE_ERROR_NONE; + // invalid state because it is starting or stopping. + if (_pending_sets.get(handle)) { + return BLE_ERROR_INVALID_STATE; + } + #if BLE_FEATURE_EXTENDED_ADVERTISING if (handle >= getMaxAdvertisingSetNumber()) { return BLE_ERROR_INVALID_PARAM; @@ -2034,6 +1934,21 @@ ble_error_t Gap::startAdvertising( } if (is_extended_advertising_available()) { + // Select the advertising address to use + address_t adv_address; + if (_privacy_enabled) { + if (_set_is_connectable.get(handle)) { + adv_address= _address_registry.get_resolvable_private_address(); + } else { + adv_address = _address_registry.get_non_resolvable_private_address(); + } + } else { + adv_address = _pal_gap.get_random_address(); + } + + // apply it + _pal_gap.set_advertising_set_random_address(handle, adv_address); + error = _pal_gap.extended_advertising_enable( /* enable */ true, /* number of advertising sets */ 1, @@ -2045,6 +1960,13 @@ ble_error_t Gap::startAdvertising( if (error) { return error; } + + if (maxDuration.value() || maxEvents) { + _interruptible_sets.clear(handle); + } else { + _interruptible_sets.set(handle); + } + } else #endif // BLE_FEATURE_EXTENDED_ADVERTISING { @@ -2052,6 +1974,32 @@ ble_error_t Gap::startAdvertising( return BLE_ERROR_INVALID_PARAM; } + // Select the advertising address to use + address_t adv_address; + if (_privacy_enabled) { + if (_scan_enabled) { + if (_central_privacy_configuration.use_non_resolvable_random_address == + _set_is_connectable.get(handle)) + { + // Conflicting state with the address currently used + return BLE_ERROR_INVALID_STATE; + } + } else { + // select the address to set + if (_set_is_connectable.get(handle)) { + adv_address= _address_registry.get_resolvable_private_address(); + } else { + adv_address = _address_registry.get_non_resolvable_private_address(); + } + } + } else { + adv_address = _pal_gap.get_random_address(); + } + + if (!_scan_enabled) { + _pal_gap.set_random_address(adv_address); + } + error = _pal_gap.advertising_enable(true); if (error) { return error; @@ -2064,9 +2012,11 @@ ble_error_t Gap::startAdvertising( maxDuration.valueChrono() ); } + + _interruptible_sets.set(LEGACY_ADVERTISING_HANDLE); } - _active_sets.set(handle); + _pending_sets.set(handle); return error; } @@ -2088,7 +2038,7 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle) } #endif // BLE_FEATURE_EXTENDED_ADVERTISING - if (!_active_sets.get(handle)) { + if (!_active_sets.get(handle) || _pending_sets.get(handle)) { return BLE_ERROR_INVALID_STATE; } @@ -2121,7 +2071,7 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle) _advertising_timeout.detach(); } - _active_sets.clear(handle); + _pending_sets.set(handle); return status; } @@ -2390,6 +2340,7 @@ void Gap::on_extended_advertising_report( *address_type == connection_peer_address_type_t::RANDOM_ADDRESS && is_random_private_resolvable_address(address.data()) ) { + // FIXME: Implement return; } #endif // BLE_FEATURE_PRIVACY @@ -2487,14 +2438,31 @@ void Gap::on_periodic_advertising_sync_loss(sync_handle_t sync_handle) void Gap::on_legacy_advertising_started() { + _active_sets.set(LEGACY_ADVERTISING_HANDLE); + _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); } void Gap::on_legacy_advertising_stopped() { + + _active_sets.clear(LEGACY_ADVERTISING_HANDLE); + _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + + // restart advertising if it was stopped to refresh the address + if (_address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE)) { + startAdvertising(LEGACY_ADVERTISING_HANDLE); + } } void Gap::on_advertising_set_started(const mbed::Span& handles) { + for (const auto &handle : handles) { + printf("advertising set %d started\r\n", handle); + _active_sets.set(handle); + _pending_sets.clear(handle); + _address_refresh_sets.clear(handle); + } } void Gap::on_advertising_set_terminated( @@ -2505,6 +2473,14 @@ void Gap::on_advertising_set_terminated( ) { _active_sets.clear(advertising_handle); + _pending_sets.clear(advertising_handle); + + // If this is part of the address refresh start advertising again. + if (_address_refresh_sets.get(advertising_handle) && !connection_handle) { + printf("restarting advertising set %d\r\n", advertising_handle); + startAdvertising(advertising_handle); + return; + } if (!_event_handler) { return; @@ -2652,11 +2628,6 @@ ble_error_t Gap::startScan( scan_period_t period ) { -#if BLE_FEATURE_PRIVACY - if (_privacy_enabled && _central_privacy_configuration.use_non_resolvable_random_address) { - set_random_address_rotation(true); - } -#endif // BLE_FEATURE_PRIVACY #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { ble_error_t err = _pal_gap.extended_scan_enable( @@ -2893,18 +2864,22 @@ bool Gap::is_extended_advertising_available() #endif // BLE_FEATURE_EXTENDED_ADVERTISING } - -void Gap::prepare_legacy_advertising_set() +ble_error_t Gap::prepare_legacy_advertising_set(const AdvertisingParameters& parameters) { if (_existing_sets.get(LEGACY_ADVERTISING_HANDLE)) { - return; + return BLE_ERROR_NONE; } - setExtendedAdvertisingParameters( + auto err = setExtendedAdvertisingParameters( LEGACY_ADVERTISING_HANDLE, - AdvertisingParameters() + parameters ); - _existing_sets.set(LEGACY_ADVERTISING_HANDLE); + + if (!err) { + _existing_sets.set(LEGACY_ADVERTISING_HANDLE); + } + + return err; } void Gap::setEventHandler(Gap::EventHandler *handler) @@ -2915,14 +2890,34 @@ void Gap::setEventHandler(Gap::EventHandler *handler) void Gap::on_resolvable_private_addresses_generated(const address_t &address) { + on_private_address_generated(true); } void Gap::on_non_resolvable_private_addresses_generated(const address_t &address) { + on_private_address_generated(false); } void Gap::on_private_address_generated(bool connectable) { + if (!_privacy_enabled) { + return; + } + + // refresh for address for all connectable advertising sets + for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { + if (!_pending_sets.get(i) && _active_sets.get(i) && + _set_is_connectable.get(i) == connectable && _interruptible_sets.get(i) + ) { + printf("stop advertising set %d\r\n", i); + auto err = stopAdvertising(i); + if (err) { + printf("failed to stop advertising set %d\r\n", i); + continue; + } + _address_refresh_sets.set(i); + } + } } @@ -2935,6 +2930,40 @@ void Gap::on_address_resolution_completion( { // FIXME: Implement } + + +bool Gap::is_advertising() const +{ + for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { + if (_pending_sets.get(i)) { + return true; + } + if (_active_sets.get(i)) { + return true; + } + if (_active_periodic_sets.get(i)) { + return true; + } + } + return false; } + +bool Gap::is_radio_active() const { + return _initiating || _scan_enabled || is_advertising(); +} + +void Gap::update_advertising_set_connectable_attribute( + advertising_handle_t handle, + const AdvertisingParameters& parameters +) +{ + if (is_connectable_advertising(parameters)) { + _set_is_connectable.set(handle); + } else { + _set_is_connectable.clear(handle); + } +} + + } // impl } // ble diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 0d9ccab86b..fedcff8090 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -405,15 +405,7 @@ private: bool initialize_whitelist() const; - ble_error_t update_address_resolution_setting(); - - void set_random_address_rotation(bool enable); - - void update_random_address(); - - bool getUnresolvableRandomAddress(ble::address_t &address); - - void on_address_rotation_timeout(); + ble_error_t update_ll_address_resolution_setting(); ble_error_t setExtendedAdvertisingParameters( advertising_handle_t handle, @@ -422,7 +414,7 @@ private: bool is_extended_advertising_available(); - void prepare_legacy_advertising_set(); + ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters); /* implements PalGap::EventHandler */ private: @@ -551,6 +543,17 @@ private: target_peer_address_type_t identity_address_type, const address_t &identity_address ) final; + +private: + bool is_advertising() const; + + bool is_radio_active() const; + + void update_advertising_set_connectable_attribute( + advertising_handle_t handle, + const AdvertisingParameters& parameters + ); + private: /** * Callchain containing all registered callback handlers for shutdown @@ -569,7 +572,6 @@ private: PalSecurityManager &_pal_sm; PrivateAddressController &_address_registry; ble::own_address_type_t _address_type; - ble::address_t _address; initiator_policy_t _initiator_policy_mode; scanning_filter_policy_t _scanning_filter_policy; advertising_filter_policy_t _advertising_filter_policy; @@ -578,8 +580,6 @@ private: bool _privacy_enabled; peripheral_privacy_configuration_t _peripheral_privacy_configuration; central_privacy_configuration_t _central_privacy_configuration; - ble::address_t _random_static_identity_address; - bool _random_address_rotating; bool _scan_enabled; mbed::LowPowerTimeout _advertising_timeout; @@ -587,6 +587,7 @@ private: mbed::LowPowerTicker _address_rotation_ticker; bool _initiating = false; + template struct BitArray { BitArray() : data() @@ -638,6 +639,10 @@ private: BitArray _active_periodic_sets; BitArray _connectable_payload_size_exceeded; BitArray _set_is_connectable; + BitArray _pending_sets; + BitArray _address_refresh_sets; + BitArray _interruptible_sets; + bool _user_manage_connection_parameter_requests : 1; }; From b8549ec91d6bdf0251c222292efef560278881f5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 16:25:31 +0100 Subject: [PATCH 14/63] BLE: rename address resolution handler. --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 2 +- connectivity/FEATURE_BLE/source/generic/GapImpl.h | 2 +- .../FEATURE_BLE/source/generic/PrivateAddressController.cpp | 2 +- .../FEATURE_BLE/source/generic/PrivateAddressController.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index c2866b23c2..bd9f6a03e1 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2921,7 +2921,7 @@ void Gap::on_private_address_generated(bool connectable) } -void Gap::on_address_resolution_completion( +void Gap::on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, target_peer_address_type_t identity_address_type, diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index fedcff8090..508405f36d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -537,7 +537,7 @@ private: void on_private_address_generated(bool connectable); - void on_address_resolution_completion( + void on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, target_peer_address_type_t identity_address_type, diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index f9fa503410..17c45d1cc7 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -507,7 +507,7 @@ private: if (!self._event_handler) { return; } - self._event_handler->on_address_resolution_completion( + self._event_handler->on_address_resolution_completed( peer_resolvable_address, resolved, identity ? identity->peer_address_type : target_peer_address_type_t::PUBLIC, diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h index 299be8d233..5b70b4fb3b 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -67,7 +67,7 @@ public: * @param identity_address_type The type of the identity address resolved. * @param identity_address The identity address resolved. */ - virtual void on_address_resolution_completion( + virtual void on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, target_peer_address_type_t identity_address_type, @@ -184,12 +184,12 @@ public: * To speedup operations, this module uses a cache to avoid too many * resolutions. If the entry is available in the cache, it is returned * immediately otherwise, the request will be completed by a report through - * EventHandler::on_address_resolution_completion + * EventHandler::on_address_resolution_completed * * @param peer_address the address to resolve. * @param resolution_complete Set to true if the resolution process has been * completed. If false, result will be made available by - * EventHandler::on_address_resolution_completion. + * EventHandler::on_address_resolution_completed. * @param retrieved_address_type The type of the address resolved. Valid if * resolution_complete is equals to true AND retrieved_address is not null. * @param retrieved_address If an entry has been found for the address in From d8c6820cbd21f6d3e36d5ce779cb681cb47913b9 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:43:43 +0100 Subject: [PATCH 15/63] BLE: Add callback for scan started and stoped. --- .../source/cordio/source/PalGapImpl.cpp | 40 ++++++++++++++----- .../source/cordio/source/PalGapImpl.h | 1 + .../FEATURE_BLE/source/generic/GapImpl.cpp | 8 ++++ .../FEATURE_BLE/source/generic/GapImpl.h | 4 ++ connectivity/FEATURE_BLE/source/pal/PalGap.h | 11 +++++ 5 files changed, 54 insertions(+), 10 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index f7c7ba29a1..644c76e8ad 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -683,16 +683,34 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) } break; #endif // BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER -#if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_OBSERVER +#if BLE_ROLE_OBSERVER + case DM_SCAN_START_IND: + if (!handler) { break; } + handler->on_scan_started(msg->status == HCI_SUCCESS); + break; + + case DM_SCAN_STOP_IND: + if (!handler) { break; } + handler->on_scan_stopped(msg->status == HCI_SUCCESS); + break; + +#if BLE_FEATURE_EXTENDED_ADVERTISING + case DM_EXT_SCAN_START_IND: + if (!handler) { break; } + handler->on_scan_started(msg->status == HCI_SUCCESS); + break; + case DM_EXT_SCAN_STOP_IND: { - if (!handler) { - break; + if (!handler) { break; } + + if (get_gap().ext_scan_stopping) { + get_gap().ext_scan_stopping = false; + handler->on_scan_stopped(msg->status == HCI_SUCCESS); + } else { + handler->on_scan_timeout(); } - //const hciLeScanTimeoutEvt_t *evt = (const hciLeScanTimeoutEvt_t *) msg; - handler->on_scan_timeout(); - } - break; + } break; case DM_EXT_SCAN_REPORT_IND: { if (!handler) { @@ -718,9 +736,9 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) evt->len, evt->pData ); - } - break; -#endif // BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_OBSERVER + } break; +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_OBSERVER #if BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL case DM_REM_CONN_PARAM_REQ_IND: { @@ -1243,6 +1261,7 @@ ble_error_t PalGap::extended_scan_enable( if (enable) { uint32_t duration_ms = duration * 10; + DmScanStart( scanning_phys.value(), DM_DISC_MODE_NONE, @@ -1253,6 +1272,7 @@ ble_error_t PalGap::extended_scan_enable( ); } else { DmScanStop(); + ext_scan_stopping = true; } return BLE_ERROR_NONE; diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h index cc581ba0d1..9b4e99fbbc 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h @@ -535,6 +535,7 @@ private: uint8_t extended_scan_type[3]; phy_set_t scanning_phys; direct_adv_cb_t direct_adv_cb[DM_NUM_ADV_SETS]; + bool ext_scan_stopping = false; /** * Callback called when an event is emitted by the LE subsystem. diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index bd9f6a03e1..633cf91193 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1051,6 +1051,14 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown() return shutdownCallChain; } +void Gap::on_scan_started(bool success) +{ +} + +void Gap::on_scan_stopped(bool success) +{ +} + void Gap::on_scan_timeout() { diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 508405f36d..1ba1146aa4 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -525,6 +525,10 @@ private: uint16_t supervision_timeout ) override; + void on_scan_started(bool success) override; + + void on_scan_stopped(bool success) override; + void on_scan_timeout() override; void process_legacy_scan_timeout(); diff --git a/connectivity/FEATURE_BLE/source/pal/PalGap.h b/connectivity/FEATURE_BLE/source/pal/PalGap.h index 425d561ab9..1a844f8d4c 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGap.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGap.h @@ -194,6 +194,17 @@ public: sync_handle_t sync_handle ) = 0; + /** + * Called when scanning start + */ + virtual void on_scan_started(bool success) = 0; + + /** + * Called when scanning stop + */ + virtual void on_scan_stopped(bool success) = 0; + + /** Called when scanning times out. */ virtual void on_scan_timeout( ) = 0; From 924f8b1dc91ebbca37b6446fd8f003555e02acc8 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:49:13 +0100 Subject: [PATCH 16/63] BLE: Update state when scan started/stopped callback received. --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 46 ++++++++++--------- .../FEATURE_BLE/source/generic/GapImpl.h | 3 +- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 633cf91193..bb6ab573bd 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -459,12 +459,10 @@ ble_error_t Gap::stopScan() { ble_error_t err; - if (!_scan_enabled) { + if ((!_scan_enabled && !_scan_pending) || _scan_pending) { return BLE_ERROR_NONE; } - _scan_enabled = false; - if (is_extended_advertising_available()) { err = _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); } else { @@ -472,10 +470,10 @@ ble_error_t Gap::stopScan() } if (err) { - _scan_enabled = true; return err; } + _scan_pending = true; _scan_timeout.detach(); return BLE_ERROR_NONE; @@ -1053,10 +1051,19 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown() void Gap::on_scan_started(bool success) { + if (success) { + _scan_pending = false; + _scan_enabled = true; + } else { + _scan_pending = false; + _scan_enabled = true; + } } void Gap::on_scan_stopped(bool success) { + _scan_pending = false; + _scan_enabled = false; } @@ -1067,29 +1074,21 @@ void Gap::on_scan_timeout() } _scan_enabled = false; + _scan_pending = false; - if (!is_extended_advertising_available()) { - /* if timeout happened on a 4.2 chip this means legacy scanning and a timer timeout - * but we need to handle the event from user context - use the event queue to handle it */ - _event_queue.post( - mbed::callback( - this, - &Gap::process_legacy_scan_timeout - ) - ); - } else { - if (_event_handler) { - _event_handler->onScanTimeout(ScanTimeoutEvent()); - } + if (_event_handler) { + _event_handler->onScanTimeout(ScanTimeoutEvent()); } } void Gap::process_legacy_scan_timeout() { + if (!_scan_enabled) { + return; + } /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); - _scan_enabled = false; if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); @@ -2666,14 +2665,17 @@ ble_error_t Gap::startScan( _scan_timeout.detach(); if (duration.value()) { - _scan_timeout.attach( - mbed::callback(this, &Gap::on_scan_timeout), + _scan_timeout.attach([this]() { + _event_queue.post([this] { process_legacy_scan_timeout(); }); + }, duration.valueChrono() ); } } - _scan_enabled = true; + if (!_scan_enabled) { + _scan_pending = true; + } return BLE_ERROR_NONE; } @@ -2957,7 +2959,7 @@ bool Gap::is_advertising() const } bool Gap::is_radio_active() const { - return _initiating || _scan_enabled || is_advertising(); + return _initiating || _scan_enabled || _scan_pending || is_advertising(); } void Gap::update_advertising_set_connectable_attribute( diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 1ba1146aa4..9e647830e8 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -585,7 +585,8 @@ private: peripheral_privacy_configuration_t _peripheral_privacy_configuration; central_privacy_configuration_t _central_privacy_configuration; - bool _scan_enabled; + bool _scan_enabled = false; + bool _scan_pending = false; mbed::LowPowerTimeout _advertising_timeout; mbed::LowPowerTimeout _scan_timeout; mbed::LowPowerTicker _address_rotation_ticker; From e5128689aa12608a9ebde3d5d82c2fd6dd99a0dd Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:49:59 +0100 Subject: [PATCH 17/63] BLE: Fix random static address storage --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 10 ++++++---- connectivity/FEATURE_BLE/source/generic/GapImpl.h | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index bb6ab573bd..34e292ccbf 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -351,6 +351,9 @@ Gap::Gap( mbed::callback(this, &Gap::on_gap_event_received) ); + // Recover static random identity + _random_static_identity_address = _pal_gap.get_random_address(); + _pal_gap.set_event_handler(this); _address_registry.set_event_handler(this); } @@ -404,12 +407,11 @@ ble_error_t Gap::setRandomStaticAddress( if (err) { return err; } - - // FIXME: set random address for active sets - - _address_type = own_address_type_t::RANDOM; } + _address_type = own_address_type_t::RANDOM; + _random_static_identity_address = address; + return BLE_ERROR_NONE; } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 9e647830e8..c76ab53697 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -584,6 +584,8 @@ private: bool _privacy_enabled; peripheral_privacy_configuration_t _peripheral_privacy_configuration; central_privacy_configuration_t _central_privacy_configuration; + ble::address_t _random_static_identity_address; + bool _scan_enabled = false; bool _scan_pending = false; From 559640cbd5bf434d46d3d1e36e6af7d4738e2057 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:50:37 +0100 Subject: [PATCH 18/63] BLE: check LL resolution availability before enabling it. --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 34e292ccbf..596cc174b7 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -920,7 +920,9 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( { _peripheral_privacy_configuration = *configuration; - update_ll_address_resolution_setting(); + if (_address_registry.is_controller_privacy_supported()) { + update_ll_address_resolution_setting(); + } return BLE_ERROR_NONE; } @@ -950,7 +952,9 @@ ble_error_t Gap::setCentralPrivacyConfiguration( { _central_privacy_configuration = *configuration; - update_ll_address_resolution_setting(); + if (_address_registry.is_controller_privacy_supported()) { + update_ll_address_resolution_setting(); + } return BLE_ERROR_NONE; } From 4685322f4ef164b2ee5db31c9364b9e64a8556d8 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:53:06 +0100 Subject: [PATCH 19/63] BLE: Add routine that computes the random address to use depending on the procedure. --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 87 +++++++++++++++++++ .../FEATURE_BLE/source/generic/GapImpl.h | 6 ++ 2 files changed, 93 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 596cc174b7..6287c9991c 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2980,6 +2980,93 @@ void Gap::update_advertising_set_connectable_attribute( } } +// Note a call to this functions implies that the +const address_t *Gap::get_random_address(controller_operation_t operation, size_t set_id) +{ + const auto &resolvable_address = _address_registry.get_resolvable_private_address(); + const auto &non_resolvable_address = _address_registry.get_non_resolvable_private_address(); + bool central_non_resolvable = _central_privacy_configuration.use_non_resolvable_random_address; + bool peripheral_non_resolvable = _peripheral_privacy_configuration.use_non_resolvable_random_address; + + const address_t *address_in_use = nullptr; + const address_t *desired_address = nullptr; + + // If privacy is not enabled, then the random address is always the random + // static address. + if (_privacy_enabled == false) { + return &_random_static_identity_address; + } + + bool advertising_use_main_address = true; + // Extended advertising is a special case as the address isn't shared with + // the main address. +#if BLE_FEATURE_EXTENDED_ADVERTISING + if (is_extended_advertising_available()) { + if (operation == controller_operation_t::advertising) { + if (_set_is_connectable.get(set_id) == false && peripheral_non_resolvable) { + return &non_resolvable_address; + } else { + return &resolvable_address; + } + } else { + advertising_use_main_address = false; + } + } +#endif + + // For other cases we first compute the address being used and then compares + // it to the address to use to determine if the address is correct or not. + if (_initiating) { + address_in_use = &resolvable_address; + } else if (_scan_enabled || _scan_pending) { + if (central_non_resolvable) { + address_in_use = &non_resolvable_address; + } else { + address_in_use = &resolvable_address; + } + } else if (advertising_use_main_address && (_active_sets.get(set_id) || _pending_sets.get(set_id))) { + if (!_set_is_connectable.get(set_id) && peripheral_non_resolvable) { + address_in_use = &non_resolvable_address; + } else { + address_in_use = &resolvable_address; + } + } else { + address_in_use = nullptr; + } + + // Compute the desired address + switch (operation) { + case controller_operation_t::initiating: + desired_address = &resolvable_address; + break; + case controller_operation_t::scanning: + if (central_non_resolvable) { + desired_address = &non_resolvable_address; + } else { + desired_address = &resolvable_address; + } + break; + case controller_operation_t::advertising: + if (!_set_is_connectable.get(set_id) && peripheral_non_resolvable) { + desired_address = &non_resolvable_address; + } else { + desired_address = &resolvable_address; + } + break; + } + + if (!address_in_use) { + return desired_address; + } + + // Request impossible to fulfill + if (address_in_use != desired_address) { + return nullptr; + } + + return desired_address; +} + } // impl } // ble diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index c76ab53697..af1339d72c 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -558,6 +558,12 @@ private: const AdvertisingParameters& parameters ); + enum class controller_operation_t { + scanning, advertising, initiating + }; + + const address_t *get_random_address(controller_operation_t operation, size_t advertising_set = 0); + private: /** * Callchain containing all registered callback handlers for shutdown From c39d03a531cd8939366b097abd2da719e6e4c77a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 22:58:01 +0100 Subject: [PATCH 20/63] BLE: Implement private address rotation for initiating. --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 148 +++++++++++++----- .../FEATURE_BLE/source/generic/GapImpl.h | 2 + 2 files changed, 107 insertions(+), 43 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 6287c9991c..99ec79691d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1068,8 +1068,46 @@ void Gap::on_scan_started(bool success) void Gap::on_scan_stopped(bool success) { + if (!success) { + _scan_pending = false; + _scan_enabled = false; + _scan_address_refresh = false; + return; + } + _scan_pending = false; _scan_enabled = false; + + // The address is refreshed only if there's no other pending request to refresh + // the main address + + bool wait_for_advertising_stop = + _address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE) && + _active_sets.get(LEGACY_ADVERTISING_HANDLE) && + _pending_sets.get(LEGACY_ADVERTISING_HANDLE); + + bool restart_advertising = + !_active_sets.get(LEGACY_ADVERTISING_HANDLE) && + !_pending_sets.get(LEGACY_ADVERTISING_HANDLE) && + _address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE); + +#ifdef BLE_FEATURE_EXTENDED_ADVERTISING + if (is_extended_advertising_available()) { + wait_for_advertising_stop = false; + restart_advertising = false; + } +#endif + + if (_scan_address_refresh && !wait_for_advertising_stop) { + if (restart_advertising) { + _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); + auto err = startAdvertising(LEGACY_ADVERTISING_HANDLE); + } + } + + _scan_address_refresh = false; + startScan(); + } } @@ -1079,6 +1117,7 @@ void Gap::on_scan_timeout() return; } + _scan_address_refresh = false; _scan_enabled = false; _scan_pending = false; @@ -1093,6 +1132,7 @@ void Gap::process_legacy_scan_timeout() if (!_scan_enabled) { return; } + /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); @@ -1927,8 +1967,9 @@ ble_error_t Gap::startAdvertising( { ble_error_t error = BLE_ERROR_NONE; - // invalid state because it is starting or stopping. - if (_pending_sets.get(handle)) { + // invalid state because it is starting, stopping or refreshing internally + // the address. + if (_pending_sets.get(handle) || _address_refresh_sets.get(handle)) { return BLE_ERROR_INVALID_STATE; } @@ -1946,21 +1987,16 @@ ble_error_t Gap::startAdvertising( return BLE_ERROR_INVALID_STATE; } - if (is_extended_advertising_available()) { - // Select the advertising address to use - address_t adv_address; - if (_privacy_enabled) { - if (_set_is_connectable.get(handle)) { - adv_address= _address_registry.get_resolvable_private_address(); - } else { - adv_address = _address_registry.get_non_resolvable_private_address(); - } - } else { - adv_address = _pal_gap.get_random_address(); - } + const address_t* random_address = get_random_address(controller_operation_t::advertising, handle); + if (!random_address) { + return BLE_ERROR_INVALID_STATE; + } - // apply it - _pal_gap.set_advertising_set_random_address(handle, adv_address); + if (is_extended_advertising_available()) { + // Addresses can be updated if the set is not advertising + if (!_active_sets.get(handle)) { + _pal_gap.set_advertising_set_random_address(handle, *random_address); + } error = _pal_gap.extended_advertising_enable( /* enable */ true, @@ -1987,30 +2023,9 @@ ble_error_t Gap::startAdvertising( return BLE_ERROR_INVALID_PARAM; } - // Select the advertising address to use - address_t adv_address; - if (_privacy_enabled) { - if (_scan_enabled) { - if (_central_privacy_configuration.use_non_resolvable_random_address == - _set_is_connectable.get(handle)) - { - // Conflicting state with the address currently used - return BLE_ERROR_INVALID_STATE; - } - } else { - // select the address to set - if (_set_is_connectable.get(handle)) { - adv_address= _address_registry.get_resolvable_private_address(); - } else { - adv_address = _address_registry.get_non_resolvable_private_address(); - } - } - } else { - adv_address = _pal_gap.get_random_address(); - } - - if (!_scan_enabled) { - _pal_gap.set_random_address(adv_address); + // Address can be updated if the device is not scanning or advertising + if (!_scan_enabled && !_scan_pending && !_active_sets.get(LEGACY_ADVERTISING_HANDLE)) { + _pal_gap.set_random_address(*random_address); } error = _pal_gap.advertising_enable(true); @@ -2453,7 +2468,6 @@ void Gap::on_legacy_advertising_started() { _active_sets.set(LEGACY_ADVERTISING_HANDLE); _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); - _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); } void Gap::on_legacy_advertising_stopped() @@ -2462,9 +2476,17 @@ void Gap::on_legacy_advertising_stopped() _active_sets.clear(LEGACY_ADVERTISING_HANDLE); _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + bool wait_for_scan_stop = _scan_enabled && _scan_pending && _scan_address_refresh; + bool restart_scan = _scan_address_refresh && !_scan_enabled && !_scan_pending; + // restart advertising if it was stopped to refresh the address - if (_address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE)) { + if (_address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE) && !wait_for_scan_stop) { + _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); startAdvertising(LEGACY_ADVERTISING_HANDLE); + if (restart_scan) { + _scan_address_refresh = false; + startScan(); + } } } @@ -2474,7 +2496,6 @@ void Gap::on_advertising_set_started(const mbed::Span& handles) printf("advertising set %d started\r\n", handle); _active_sets.set(handle); _pending_sets.clear(handle); - _address_refresh_sets.clear(handle); } } @@ -2491,6 +2512,7 @@ void Gap::on_advertising_set_terminated( // If this is part of the address refresh start advertising again. if (_address_refresh_sets.get(advertising_handle) && !connection_handle) { printf("restarting advertising set %d\r\n", advertising_handle); + _address_refresh_sets.clear(advertising_handle); startAdvertising(advertising_handle); return; } @@ -2590,6 +2612,10 @@ void Gap::on_remote_connection_parameter( #if BLE_ROLE_OBSERVER ble_error_t Gap::setScanParameters(const ScanParameters ¶ms) { + if (_privacy_enabled && params.getOwnAddressType() != own_address_type_t::RANDOM) { + return BLE_ERROR_INVALID_PARAM; + } + if (is_extended_advertising_available()) { bool active_scanning[] = { params.get1mPhyConfiguration().isActiveScanningSet(), @@ -2641,8 +2667,21 @@ ble_error_t Gap::startScan( scan_period_t period ) { + if (_scan_pending || _scan_address_refresh) { + return BLE_ERROR_INVALID_STATE; + } + + const address_t *address = get_random_address(controller_operation_t::scanning); + if (!address) { + return BLE_ERROR_INVALID_STATE; + } #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { + // set the correct mac address before starting scanning. + if (!_scan_enabled) { + _pal_gap.set_random_address(*address); + } + ble_error_t err = _pal_gap.extended_scan_enable( /* enable */true, filtering, @@ -2660,6 +2699,12 @@ ble_error_t Gap::startScan( return BLE_ERROR_INVALID_PARAM; } + // update the address if no scan or advertising is running + auto adv_handle = LEGACY_ADVERTISING_HANDLE; + if (!_scan_enabled && !_active_sets.get(adv_handle) && !_pending_sets.get(adv_handle)) { + _pal_gap.set_random_address(*address); + } + ble_error_t err = _pal_gap.scan_enable( true, filtering == duplicates_filter_t::DISABLE ? false : true @@ -2682,6 +2727,11 @@ ble_error_t Gap::startScan( if (!_scan_enabled) { _scan_pending = true; } + if (duration == scan_duration_t::forever() && period == scan_period_t(0)) { + _scan_interruptible = true; + } else { + _scan_interruptible = false; + } return BLE_ERROR_NONE; } @@ -2920,6 +2970,7 @@ void Gap::on_private_address_generated(bool connectable) return; } + // refresh for address for all connectable advertising sets for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { if (!_pending_sets.get(i) && _active_sets.get(i) && @@ -2934,6 +2985,17 @@ void Gap::on_private_address_generated(bool connectable) _address_refresh_sets.set(i); } } + + // refresh scanning address + if (_scan_enabled && !_scan_pending && _scan_interruptible && + !_central_privacy_configuration.use_non_resolvable_random_address == connectable + ) { + ble_error_t err = stopScan(); + if (err) { + return; + } + _scan_address_refresh = true; + } } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index af1339d72c..b409241b78 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -595,6 +595,8 @@ private: bool _scan_enabled = false; bool _scan_pending = false; + bool _scan_interruptible = false; + bool _scan_address_refresh = false; mbed::LowPowerTimeout _advertising_timeout; mbed::LowPowerTimeout _scan_timeout; mbed::LowPowerTicker _address_rotation_ticker; From 19d89366d74e41a357da16fba65adfa406fb0751 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 23:26:43 +0100 Subject: [PATCH 21/63] BLE: Private address when initiating connection --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 99ec79691d..30fd6263ee 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -509,6 +509,12 @@ ble_error_t Gap::connect( } } + // get the random address to set, if not valid, report the error + const address_t *address = get_random_address(controller_operation_t::initiating); + if (!address) { + return BLE_ERROR_INVALID_STATE; + } + ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; if (is_extended_advertising_available() == false) { @@ -517,8 +523,16 @@ ble_error_t Gap::connect( return BLE_ERROR_INVALID_PARAM; } - // ensure scan is stopped. - _pal_gap.scan_enable(false, false); + if (!_scan_enabled) { + if (!_active_sets.get(LEGACY_ADVERTISING_HANDLE) && + !_pending_sets.get(LEGACY_ADVERTISING_HANDLE) + ) { + _pal_gap.set_random_address(*address); + } + } else { + // ensure scan is stopped. + _pal_gap.scan_enable(false, false); + } ret = _pal_gap.create_connection( connectionParams.getScanIntervalArray()[0], @@ -535,8 +549,13 @@ ble_error_t Gap::connect( connectionParams.getMaxConnectionIntervalArray()[0] ); } else { - // ensure scan is stopped. - _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); + // set the correct mac address before starting scanning. + if (!_scan_enabled) { + _pal_gap.set_random_address(*address); + } else { + // ensure scan is stopped. + _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); + } // reduce the address type to public or random peer_address_type_t adjusted_address_type(peer_address_type_t::PUBLIC); From 3c22f8ae1dc3f715d3aa1e17e8ca8302f5216d28 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 9 Sep 2020 23:34:10 +0100 Subject: [PATCH 22/63] BLE: privacy tracing cleanup --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 30fd6263ee..35ed0250f7 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1120,8 +1120,7 @@ void Gap::on_scan_stopped(bool success) if (_scan_address_refresh && !wait_for_advertising_stop) { if (restart_advertising) { _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); - auto err = startAdvertising(LEGACY_ADVERTISING_HANDLE); - } + startAdvertising(LEGACY_ADVERTISING_HANDLE); } _scan_address_refresh = false; @@ -2512,7 +2511,6 @@ void Gap::on_legacy_advertising_stopped() void Gap::on_advertising_set_started(const mbed::Span& handles) { for (const auto &handle : handles) { - printf("advertising set %d started\r\n", handle); _active_sets.set(handle); _pending_sets.clear(handle); } @@ -2530,7 +2528,6 @@ void Gap::on_advertising_set_terminated( // If this is part of the address refresh start advertising again. if (_address_refresh_sets.get(advertising_handle) && !connection_handle) { - printf("restarting advertising set %d\r\n", advertising_handle); _address_refresh_sets.clear(advertising_handle); startAdvertising(advertising_handle); return; @@ -2995,10 +2992,8 @@ void Gap::on_private_address_generated(bool connectable) if (!_pending_sets.get(i) && _active_sets.get(i) && _set_is_connectable.get(i) == connectable && _interruptible_sets.get(i) ) { - printf("stop advertising set %d\r\n", i); auto err = stopAdvertising(i); if (err) { - printf("failed to stop advertising set %d\r\n", i); continue; } _address_refresh_sets.set(i); From 48f4cfbe042e1c901a83d508a2f6c019b9c2ed31 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 10 Sep 2020 14:57:56 +0100 Subject: [PATCH 23/63] BLE: return stack busy instead of invalid state when applicable enabling/disabling scanning and advertising operations can be prevented if the previous operations hasn't completed. Return that the stack is busy and cannot fulfill the request at the moment rather than the state is invalid. --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 35ed0250f7..9812e5969d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -462,7 +462,7 @@ ble_error_t Gap::stopScan() ble_error_t err; if ((!_scan_enabled && !_scan_pending) || _scan_pending) { - return BLE_ERROR_NONE; + return BLE_STACK_BUSY; } if (is_extended_advertising_available()) { @@ -1985,10 +1985,10 @@ ble_error_t Gap::startAdvertising( { ble_error_t error = BLE_ERROR_NONE; - // invalid state because it is starting, stopping or refreshing internally + // the stack is busy because it is starting, stopping or refreshing internally // the address. if (_pending_sets.get(handle) || _address_refresh_sets.get(handle)) { - return BLE_ERROR_INVALID_STATE; + return BLE_STACK_BUSY; } #if BLE_FEATURE_EXTENDED_ADVERTISING @@ -2085,7 +2085,7 @@ ble_error_t Gap::stopAdvertising(advertising_handle_t handle) #endif // BLE_FEATURE_EXTENDED_ADVERTISING if (!_active_sets.get(handle) || _pending_sets.get(handle)) { - return BLE_ERROR_INVALID_STATE; + return BLE_STACK_BUSY; } #if BLE_FEATURE_EXTENDED_ADVERTISING @@ -2684,7 +2684,7 @@ ble_error_t Gap::startScan( ) { if (_scan_pending || _scan_address_refresh) { - return BLE_ERROR_INVALID_STATE; + return BLE_STACK_BUSY; } const address_t *address = get_random_address(controller_operation_t::scanning); From 9df7fc9b7e603f21cd7216ee9bb085338a993caa Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 10 Sep 2020 14:58:35 +0100 Subject: [PATCH 24/63] BLE: Fix state update when event handler not present --- connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index 644c76e8ad..80bdea8ae1 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -701,7 +701,10 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) break; case DM_EXT_SCAN_STOP_IND: { - if (!handler) { break; } + if (!handler) { + get_gap().ext_scan_stopping = false; + break; + } if (get_gap().ext_scan_stopping) { get_gap().ext_scan_stopping = false; From 9eac36879a82878b7d95b5e0ca5dd409bbea45d9 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 10 Sep 2020 14:59:03 +0100 Subject: [PATCH 25/63] BLE: improve scan state bookkeeping --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 9812e5969d..44aa14497d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1076,27 +1076,20 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown() void Gap::on_scan_started(bool success) { - if (success) { - _scan_pending = false; - _scan_enabled = true; - } else { - _scan_pending = false; - _scan_enabled = true; - } + _scan_pending = false; + _scan_enabled = success; } void Gap::on_scan_stopped(bool success) { + _scan_pending = false; + _scan_enabled = false; + if (!success) { - _scan_pending = false; - _scan_enabled = false; _scan_address_refresh = false; return; } - _scan_pending = false; - _scan_enabled = false; - // The address is refreshed only if there's no other pending request to refresh // the main address From f897729d5c2f1bb19c845d53090a538278f3abb5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Thu, 10 Sep 2020 17:12:44 +0100 Subject: [PATCH 26/63] Cordio: Add API to set the local identity address. --- .../cordio_stack/ble-host/include/dm_api.h | 31 +++++++++++ .../ble-host/sources/stack/dm/dm_sec.c | 52 +++++++++++++++++++ .../ble-host/sources/stack/dm/dm_sec.h | 2 + .../ble-host/sources/stack/smp/smp_act.c | 4 +- 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h index daadd5d91f..04271c308f 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/include/dm_api.h @@ -3035,6 +3035,18 @@ void DmSecSetLocalCsrk(uint8_t *pCsrk); /*************************************************************************************************/ void DmSecSetLocalIrk(uint8_t *pIrk); +/*************************************************************************************************/ +/*! + * \brief This function sets the local identity address used by the device. + * + * \param pAddr Pointer to the address. + * \param type Type of the address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type); + /*************************************************************************************************/ /*! * \brief This function generates an ECC key for use with LESC security. @@ -3345,6 +3357,25 @@ uint8_t *DmSecGetLocalCsrk(void); /*************************************************************************************************/ uint8_t *DmSecGetLocalIrk(void); +/*************************************************************************************************/ +/*! + * \brief For internal use only. This function gets the local identity address used by the device. + * + * \return Pointer to the identity address. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalIdentityAddr(void); + +/*************************************************************************************************/ +/*! + * \brief For internal use only. This function gets the local identity address type used by the + * device. + * + * \return The identity address type. + */ +/*************************************************************************************************/ +uint8_t DmSecGetLocalIdentityAddrType(void); + /*************************************************************************************************/ /*! * \brief For internal use only. Read the features of the remote device. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c index 7d66f73b32..c3869e3ec6 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.c @@ -329,6 +329,7 @@ void DmSecInit(void) dmFcnIfTbl[DM_ID_SEC] = (dmFcnIf_t *) &dmSecFcnIf; dmSecCb.pCsrk = dmSecCb.pIrk = (uint8_t *) calc128Zeros; + dmSecCb.addrType = DM_ADDR_NONE; } /*************************************************************************************************/ @@ -363,6 +364,24 @@ void DmSecSetLocalIrk(uint8_t *pIrk) WsfTaskUnlock(); } +/*************************************************************************************************/ +/*! + * \brief This function sets the local identity address used by the device. + * + * \param pAddr Pointer to the address. + * \param type Type of the address. + * + * \return None. + */ +/*************************************************************************************************/ +void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type) +{ + WsfTaskLock(); + dmSecCb.addrType = type; + BdaCpy(dmSecCb.bdAddr, pAddr); + WsfTaskUnlock(); +} + /*************************************************************************************************/ /*! * \brief This function gets the local CSRK used by the device. @@ -387,6 +406,39 @@ uint8_t *DmSecGetLocalIrk(void) return dmSecCb.pIrk; } +/*************************************************************************************************/ +/*! + * \brief For internal use only. This function gets the local identity address used by the device. + * + * \return Pointer to the identity address. + */ +/*************************************************************************************************/ +uint8_t *DmSecGetLocalIdentityAddr(void) +{ + if (dmSecCb.addrType != DM_ADDR_NONE) { + return dmSecCb.bdAddr; + } else { + return HciGetBdAddr(); + } +} + +/*************************************************************************************************/ +/*! + * \brief For internal use only. This function gets the local identity address type used by the + * device. + * + * \return The identity address type. + */ +/*************************************************************************************************/ +uint8_t DmSecGetLocalIdentityAddrType(void) +{ + if (dmSecCb.addrType != DM_ADDR_NONE) { + return dmSecCb.addrType; + } else { + return DM_ADDR_PUBLIC; + } +} + /*************************************************************************************************/ /*! * \brief Reset the sec module. diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h index 6aa292a70b..7f3dd58113 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/dm/dm_sec.h @@ -83,6 +83,8 @@ typedef struct { uint8_t *pIrk; uint8_t *pCsrk; + bdAddr_t bdAddr; + uint8_t addrType; } dmSecCb_t; /************************************************************************************************** diff --git a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c index 3c1ac36652..486c55cebd 100644 --- a/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c +++ b/connectivity/FEATURE_BLE/libraries/cordio_stack/ble-host/sources/stack/smp/smp_act.c @@ -567,8 +567,8 @@ bool_t smpSendKey(smpCcb_t *pCcb, uint8_t keyDist) { /* send second part of IRK */ UINT8_TO_BSTREAM(p, SMP_CMD_ID_ADDR_INFO); - UINT8_TO_BSTREAM(p, DM_ADDR_PUBLIC); - BDA_TO_BSTREAM(p, HciGetBdAddr()); + UINT8_TO_BSTREAM(p, DmSecGetLocalIdentityAddrType()); + BDA_TO_BSTREAM(p, DmSecGetLocalIdentityAddr()); } else if ((keyDist & SMP_KEY_DIST_SIGN) && From 5cb05958a9477fd85f0a1602491b86b41b632088 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 16 Sep 2020 14:01:05 +0100 Subject: [PATCH 27/63] BLE: Add function to get the device random static address. --- connectivity/FEATURE_BLE/include/ble/Gap.h | 2 ++ connectivity/FEATURE_BLE/source/Gap.cpp | 5 +++++ connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 4 ++++ connectivity/FEATURE_BLE/source/generic/GapImpl.h | 2 ++ 4 files changed, 13 insertions(+) diff --git a/connectivity/FEATURE_BLE/include/ble/Gap.h b/connectivity/FEATURE_BLE/include/ble/Gap.h index ed8cfe2c72..88dd9b5824 100644 --- a/connectivity/FEATURE_BLE/include/ble/Gap.h +++ b/connectivity/FEATURE_BLE/include/ble/Gap.h @@ -1448,6 +1448,8 @@ public: * forbidden by the Bluetooth specification. */ ble_error_t setRandomStaticAddress(const ble::address_t& address); + + ble::address_t getRandomStaticAddress(); #endif // !defined(DOXYGEN_ONLY) private: diff --git a/connectivity/FEATURE_BLE/source/Gap.cpp b/connectivity/FEATURE_BLE/source/Gap.cpp index 727d2a285c..b45031807f 100644 --- a/connectivity/FEATURE_BLE/source/Gap.cpp +++ b/connectivity/FEATURE_BLE/source/Gap.cpp @@ -501,4 +501,9 @@ ble_error_t Gap::setRandomStaticAddress(const ble::address_t &address) return impl->setRandomStaticAddress(address); } +ble::address_t Gap::getRandomStaticAddress() +{ + return impl->getRandomStaticAddress(); +} + } // namespace ble \ No newline at end of file diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 44aa14497d..b194ba6cf9 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -415,6 +415,10 @@ ble_error_t Gap::setRandomStaticAddress( return BLE_ERROR_NONE; } +ble::address_t Gap::getRandomStaticAddress() +{ + return _random_static_identity_address; +} ble_error_t Gap::getAddress( own_address_type_t &type, diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index b409241b78..522f797e67 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -346,6 +346,8 @@ public: */ ble_error_t setRandomStaticAddress(const ble::address_t &address); + ble::address_t getRandomStaticAddress(); + #endif // !defined(DOXYGEN_ONLY) /* ===================================================================== */ From 0b9868210931823a391f601d20a20c1436bc163b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 16 Sep 2020 14:02:55 +0100 Subject: [PATCH 28/63] BLE: Add function to set the identity address used by the controller/platform. The function to get it has been removed as this operation is driven by the security manager. --- .../cordio/source/PalSecurityManagerImpl.cpp | 26 ++++++++----------- .../cordio/source/PalSecurityManagerImpl.h | 12 +++++---- .../source/pal/PalSecurityManager.h | 26 +++++++++---------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp index 772f7fa3a2..993bb4d482 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp @@ -220,21 +220,6 @@ ble_error_t PalSecurityManager::set_private_address_timeout( return BLE_ERROR_NONE; } -/** - * @see ::ble::PalSecurityManager::get_identity_address - */ - -ble_error_t PalSecurityManager::get_identity_address( - address_t &address, - bool &public_address -) -{ - // On cordio, the public address is hardcoded as the identity address. - address = address_t(HciGetBdAddr()); - public_address = true; - return BLE_ERROR_NONE; -} - //////////////////////////////////////////////////////////////////////////// // Keys // @@ -288,6 +273,17 @@ ble_error_t PalSecurityManager::set_irk(const irk_t &irk) return BLE_ERROR_NONE; } +ble_error_t PalSecurityManager::set_identity_address( + const address_t &address, + bool public_address +) +{ + DmSecSetLocalIdentityAddr( + address.data(), + public_address ? DM_ADDR_PUBLIC : DM_ADDR_RANDOM + ); + return BLE_ERROR_NONE; +} ble_error_t PalSecurityManager::set_csrk( const csrk_t &csrk, diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h index ec955653f6..e38e37431e 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h @@ -183,11 +183,6 @@ public: */ ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds) final; - /** - * @see ::ble::PalSecurityManager::get_identity_address - */ - ble_error_t get_identity_address(address_t &address, bool &public_address) final; - //////////////////////////////////////////////////////////////////////////// // Keys // @@ -214,6 +209,13 @@ public: */ ble_error_t set_irk(const irk_t &irk) final; + /** + * @see ::ble::PalSecurityManager::set_identity_address + */ + ble_error_t set_identity_address( + const address_t &address, bool public_address + ) final; + /** * @see ::ble::PalSecurityManager::set_csrk */ diff --git a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h index 5a4e09cb8c..99caec6d8e 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h +++ b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h @@ -761,20 +761,6 @@ public: uint16_t timeout_in_seconds ) = 0; - /** - * Retrieve the identity address used by the controller - * - * @param address Will contain the address retrieved. - * @param public_address will be true if the address is public and false - * otherwise. - * @return BLE_ERROR_NONE On success, else an error code indicating the reason - * of the failure - */ - virtual ble_error_t get_identity_address( - address_t& address, - bool& public_address - ) = 0; - //////////////////////////////////////////////////////////////////////////// // Keys // @@ -814,6 +800,18 @@ public: virtual ble_error_t set_irk( const irk_t &irk ) = 0; + + /** + * Set the local identity address. + * + * @param[in] address identity address of the device + * @param[in] public_address true if a public address is used and false otherwise. + * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure + */ + virtual ble_error_t set_identity_address( + const address_t &address, bool public_address + ) = 0; + /** * Set the local CSRK. * From 4859dbe4265dd086b8a82bcf450cf3f5f090640b Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 16 Sep 2020 15:26:16 +0100 Subject: [PATCH 29/63] BLE: Set identity address to random static. This also ensure the random static address used by gap is the correct one. --- .../FEATURE_BLE/source/generic/SecurityDb.h | 14 +++++++++++++ .../source/generic/SecurityManagerImpl.cpp | 21 +++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityDb.h b/connectivity/FEATURE_BLE/source/generic/SecurityDb.h index e6a24e709a..3cf01f35f4 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityDb.h +++ b/connectivity/FEATURE_BLE/source/generic/SecurityDb.h @@ -450,6 +450,20 @@ public: return _local_identity.irk; } + /** + * Return local identity address. + */ + virtual const address_t& get_local_identity_address() { + return _local_identity.identity_address; + } + + /** + * Return if the local identity address is public or not + */ + virtual bool is_local_identity_address_public() { + return _local_identity.identity_address_is_public; + } + /* list management */ /** diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index ef56f3f70d..3f3427e8d5 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -1032,9 +1032,24 @@ ble_error_t SecurityManager::init_identity() if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; const irk_t *pirk = nullptr; + ble::Gap& gap = BLE::Instance().gap(); + irk_t irk = _db->get_local_irk(); if (irk != irk_t()) { pirk = &irk; + + if (!_db->is_local_identity_address_public()) { + // Some controllers doesn't store their random static address and + // instead generates them at each reboot. + // The code should replace the random static address with the identity + // address if this is the case. + if (_db->get_local_identity_address() != gap.getRandomStaticAddress()) { + ble_error_t err = gap.setRandomStaticAddress(_db->get_local_identity_address()); + if (err) { + return err; + } + } + } } else { ble_error_t ret = get_random_data(irk.data(), irk.size()); if (ret != BLE_ERROR_NONE) { @@ -1042,13 +1057,11 @@ ble_error_t SecurityManager::init_identity() } pirk = &irk; - address_t identity_address; - bool public_address; - ret = _pal.get_identity_address(identity_address, public_address); + address_t random_static_address = gap.getRandomStaticAddress(); if (ret != BLE_ERROR_NONE) { return ret; } - _db->set_local_identity(irk, identity_address, public_address); + _db->set_local_identity(irk, random_static_address, /* public_address */ false); } auto err = _pal.set_irk(*pirk); From 685af00fd53aac0f306c0edee8a8f0d928dd86b7 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 16 Sep 2020 09:28:04 +0100 Subject: [PATCH 30/63] split resolve addres into cache and not cache --- .../generic/PrivateAddressController.cpp | 37 +++++++++++++------ .../source/generic/PrivateAddressController.h | 30 ++++++++++++++- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index 17c45d1cc7..1a9b938c92 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -234,24 +234,18 @@ ble_error_t PrivateAddressController::clear_resolving_list() } } -ble_error_t PrivateAddressController::resolve_address( +bool PrivateAddressController::resolve_address_in_cache( const address_t &peer_address, - bool *resolution_complete, target_peer_address_type_t *retrieved_address_type, const address_t **retrieved_address ) { - if (is_controller_privacy_supported()) { - return BLE_ERROR_NOT_IMPLEMENTED; - } - // An LRU cache is used, we first traverse the list of resolved address // and return any match auto *entry = _resolved_list; decltype(entry) previous = nullptr; while (entry) { if (entry->address == peer_address) { - *resolution_complete = true; // The list contains resolved addresses AND unresolved addresses. // Fill input parameters accordingly if (entry->identity) { @@ -266,16 +260,35 @@ ble_error_t PrivateAddressController::resolve_address( entry->next = _resolved_list; _resolved_list = entry; } - return BLE_ERROR_NONE; + return true; } previous = entry; entry = entry->next; } + return false; +} + +ble_error_t PrivateAddressController::resolve_address( + const address_t &peer_address, + bool *resolution_complete, + target_peer_address_type_t *retrieved_address_type, + const address_t **retrieved_address +) +{ + if (is_controller_privacy_supported()) { + return BLE_ERROR_NOT_IMPLEMENTED; + } + + *resolution_complete = resolve_address_in_cache(peer_address, retrieved_address_type, retrieved_address); + // In the case the address has not been resolved, we start the resolution // process. - *resolution_complete = false; - return queue_resolve_address(peer_address); + if (*resolution_complete) { + return BLE_ERROR_NONE; + } else { + return queue_resolve_address(peer_address); + } } void PrivateAddressController::on_resolving_list_action_complete() @@ -667,4 +680,4 @@ void PrivateAddressController::add_resolution_entry_to_cache( _resolved_list = entry; } -} // namespace ble \ No newline at end of file +} // namespace ble diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h index 5b70b4fb3b..2d7a0f7aad 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -203,7 +203,34 @@ public: const address_t **retrieved_address ); + /** + * Resolve a private address by looking in the cache. + * + * @param peer_address the address to resolve. + * @param retrieved_address_type The type of the address resolved. Valid if + * resolution_complete is equals to true AND retrieved_address is not null. + * @param retrieved_address If an entry has been found for the address in + * input this will be set to null if the address has not been resolved with + * the local irks or a pointer to the identity address if it has been resolved. + * + * @return True if the address has been found in cache. + */ + bool resolve_address_in_cache( + const address_t &peer_address, + target_peer_address_type_t *retrieved_address_type, + const address_t **retrieved_address + ); + + /** + * Resolve a private resolvable address asynchronously. The request will be completed by a report through + * EventHandler::on_address_resolution_completed. + * + * @param peer_address the address to resolve. + */ + ble_error_t queue_resolve_address(const address_t &peer_address); + private: + void generate_resolvable_address(); void generate_non_resolvable_address(); @@ -243,7 +270,6 @@ private: ble_error_t queue_clear_resolving_list(); struct PrivacyResolveAddress; - ble_error_t queue_resolve_address(const address_t &peer_address); void restart_resolution_process(); From 0a3cd69fc66c8ca5389cfb3d699371f0e2ebc78e Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Thu, 17 Sep 2020 12:26:34 +0100 Subject: [PATCH 31/63] event handler should not affect internal state --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index b194ba6cf9..f28e4da1e1 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2333,13 +2333,14 @@ void Gap::on_enhanced_connection_complete( clock_accuracy_t master_clock_accuracy ) { + if (own_role == connection_role_t::CENTRAL) { + _initiating = false; + } + if (!_event_handler) { return; } - if (own_role == connection_role_t::CENTRAL) { - _initiating = false; - } _event_handler->onConnectionComplete( ConnectionCompleteEvent( From df17942c2c5f2e2cf82866215e8825adb74363de Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Thu, 17 Sep 2020 17:18:23 +0100 Subject: [PATCH 32/63] remove unused enhanced conn complete --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 42 --------------- .../FEATURE_BLE/source/generic/GapImpl.h | 14 ----- connectivity/FEATURE_BLE/source/pal/PalGap.h | 53 ------------------- 3 files changed, 109 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index f28e4da1e1..789ec49eca 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2318,48 +2318,6 @@ bool Gap::isPeriodicAdvertisingActive(advertising_handle_t handle) #endif #endif - -void Gap::on_enhanced_connection_complete( - hci_error_code_t status, - connection_handle_t connection_handle, - connection_role_t own_role, - connection_peer_address_type_t peer_address_type, - const ble::address_t &peer_address, - const ble::address_t &local_resolvable_private_address, - const ble::address_t &peer_resolvable_private_address, - uint16_t connection_interval, - uint16_t connection_latency, - uint16_t supervision_timeout, - clock_accuracy_t master_clock_accuracy -) -{ - if (own_role == connection_role_t::CENTRAL) { - _initiating = false; - } - - if (!_event_handler) { - return; - } - - - _event_handler->onConnectionComplete( - ConnectionCompleteEvent( - (status == hci_error_code_t::SUCCESS) ? BLE_ERROR_NONE : BLE_ERROR_INTERNAL_STACK_FAILURE, - (connection_handle_t) connection_handle, - own_role, - (peer_address_type_t::type) peer_address_type.value(), - peer_address, - local_resolvable_private_address, - peer_resolvable_private_address, - conn_interval_t(connection_interval), - connection_latency, - supervision_timeout_t(supervision_timeout), - master_clock_accuracy.get_ppm() - ) - ); -} - - void Gap::on_extended_advertising_report( advertising_event_t event_type, const connection_peer_address_type_t *address_type, diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 522f797e67..5333907fd8 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -440,20 +440,6 @@ private: phy_t rx_phy ) override; - void on_enhanced_connection_complete( - hci_error_code_t status, - connection_handle_t connection_handle, - connection_role_t own_role, - connection_peer_address_type_t peer_address_type, - const ble::address_t &peer_address, - const ble::address_t &local_resolvable_private_address, - const ble::address_t &peer_resolvable_private_address, - uint16_t connection_interval, - uint16_t connection_latency, - uint16_t supervision_timeout, - clock_accuracy_t master_clock_accuracy - ) override; - void on_extended_advertising_report( advertising_event_t event_type, const connection_peer_address_type_t *address_type, diff --git a/connectivity/FEATURE_BLE/source/pal/PalGap.h b/connectivity/FEATURE_BLE/source/pal/PalGap.h index 1a844f8d4c..ca538de892 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGap.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGap.h @@ -58,59 +58,6 @@ public: ble::phy_t rx_phy ) = 0; - /** - * Should be invoked by the PalGap implementation when an enhanced - * connection complete event happens. - * - * @param status hci_error_code::SUCCESS in case of success or an error - * code. - * - * @param connection_handle The handle of the connection created. - * - * @param own_role Indicate if the local device operates as slave or - * master. - * - * @param peer_address_type Type of address of the peer. - * - * @param peer_address Address of the peer connected. - * - * @param local_resolvable_private_address Resolvable private address - * being used by the controller. If not applicable, the address is full - * of zeroes. - * - * @param peer_resolvable_private_address Resolvable private address - * being used by the peer. If not applicable, the address is full of - * zeroes. - * - * @param connection_interval Interval between two connection events. - * Unit is 1.25ms. - * - * @param connection_latency Slave latency for the connection in number - * of connection events. - * - * @param supervision_timeout Connection supervision timeout. Unit is - * 10ms. - * - * @param master_clock_accuracy This parameter is only valid for a slave. - * On a master it must be set to 0x00. - * - * @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE enhanced connection - * complete event. - */ - virtual void on_enhanced_connection_complete( - hci_error_code_t status, - connection_handle_t connection_handle, - connection_role_t own_role, - connection_peer_address_type_t peer_address_type, - const address_t &peer_address, - const address_t &local_resolvable_private_address, - const address_t &peer_resolvable_private_address, - uint16_t connection_interval, - uint16_t connection_latency, - uint16_t supervision_timeout, - clock_accuracy_t master_clock_accuracy - ) = 0; - /** Called on advertising report event. * * @param event_type Type of advertising used. From 44b2e73ef1dfef3102b3153a8dd4fe764577f9a5 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Tue, 22 Sep 2020 09:18:21 +0100 Subject: [PATCH 33/63] Add setters to events --- .../FEATURE_BLE/include/ble/gap/Events.h | 78 ++++++++++++++++--- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/gap/Events.h b/connectivity/FEATURE_BLE/include/ble/gap/Events.h index b8f561a12c..022b6035c1 100644 --- a/connectivity/FEATURE_BLE/include/ble/gap/Events.h +++ b/connectivity/FEATURE_BLE/include/ble/gap/Events.h @@ -69,15 +69,15 @@ struct AdvertisingReportEvent { const address_t &directAddress, const mbed::Span &advertisingData ) : + peerAddress(peerAddress), type(type), peerAddressType(peerAddressType), - peerAddress(peerAddress), primaryPhy(primaryPhy), secondaryPhy(secondaryPhy), SID(SID), txPower(txPower), - rssi(rssi), periodicInterval(periodicInterval), + rssi(rssi), directAddressType(directAddressType), directAddress(directAddress), advertisingData(advertisingData) @@ -85,7 +85,6 @@ struct AdvertisingReportEvent { } #endif - /** Get event type. */ const advertising_event_t &getType() const { @@ -163,18 +162,44 @@ struct AdvertisingReportEvent { return advertisingData; } + /** Set peer address. */ + void setPeerAddress( + const address_t &newPeerAddress + ) + { + peerAddress = newPeerAddress; + } + + + /** Set peer address type. */ + void setPeerAddressType( + const peer_address_type_t &newPeerAddressType + ) + { + peerAddressType = newPeerAddressType; + } + + /** Set new advertising payload. */ + void setAdvertisingData( + const mbed::Span &newAdvertisingData + ) + { + advertisingData = newAdvertisingData; + } + private: + address_t peerAddress; advertising_event_t type; peer_address_type_t peerAddressType; - address_t const &peerAddress; phy_t primaryPhy; phy_t secondaryPhy; advertising_sid_t SID; advertising_power_t txPower; - rssi_t rssi; uint16_t periodicInterval; + rssi_t rssi; peer_address_type_t directAddressType; - const address_t &directAddress; + address_t directAddress; + ble_error_t status; mbed::Span advertisingData; }; @@ -215,12 +240,12 @@ struct ConnectionCompleteEvent { ) : status(status), connectionHandle(connectionHandle), + peerAddress(peerAddress), ownRole(ownRole), peerAddressType(peerAddressType), - peerAddress(peerAddress), localResolvablePrivateAddress(localResolvablePrivateAddress), - peerResolvablePrivateAddress(peerResolvablePrivateAddress), connectionInterval(connectionInterval), + peerResolvablePrivateAddress(peerResolvablePrivateAddress), connectionLatency(connectionLatency), supervisionTimeout(supervisionTimeout), masterClockAccuracy(masterClockAccuracy) @@ -295,15 +320,46 @@ struct ConnectionCompleteEvent { return masterClockAccuracy; } + + /** Set connection complete event status. */ + void setStatus(ble_error_t new_status) + { + status = new_status; + } + + /** Set peer address type. */ + void setPeerAddressType(const peer_address_type_t& address_type) + { + peerAddressType = address_type; + } + + /** Set peer address. */ + void setPeerAddress(const address_t &address) + { + peerAddress = address; + } + + /** Set get local resolvable random address if privacy is used. */ + void setLocalResolvablePrivateAddress(const address_t &address) + { + localResolvablePrivateAddress = address; + } + + /** Set peer resolvable private address if privacy is used. */ + void setPeerResolvablePrivateAddress(const address_t &address) + { + peerResolvablePrivateAddress = address; + } + private: ble_error_t status; connection_handle_t connectionHandle; + address_t peerAddress; connection_role_t ownRole; peer_address_type_t peerAddressType; - const address_t &peerAddress; - const address_t &localResolvablePrivateAddress; - const address_t &peerResolvablePrivateAddress; + address_t localResolvablePrivateAddress; conn_interval_t connectionInterval; + address_t peerResolvablePrivateAddress; slave_latency_t connectionLatency; supervision_timeout_t supervisionTimeout; uint16_t masterClockAccuracy; From 593c1776b48c641b300a6df6ba0e27916da3bba2 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Tue, 22 Sep 2020 09:19:23 +0100 Subject: [PATCH 34/63] add EventList class for storing pending events --- .../FEATURE_BLE/source/generic/GapImpl.h | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 5333907fd8..b5e7b8d2cb 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -353,6 +353,146 @@ public: /* ===================================================================== */ /* private implementation follows */ +private: + /** List in random order */ + template + class EventList { + public: + EventList() + { + }; + + ~EventList() + { + for (IndexType i = 0; i < _current_size; ++i) { + delete _pointers[i]; + } + }; + + /** Add event to the list. List takes ownership of memory. + * + * @param event List will point to this event. + * @return False if list full. + */ + bool push(EventType *event) + { + if (_current_size < MAX_EVENTS) { + _pointers[_current_size] = event; + _current_size++; + return true; + } + return false; + }; + + /** Take one entry of the list. Transfers ownership to caller. + * + * @return The event return. Memory belongs to caller. + */ + EventType* pop() + { + MBED_ASSERT(_current_size); + + if (!_current_size) { + return nullptr; + } + + EventType* event_returned = _pointers[_current_index]; + + _current_size--; + if (_current_size != _current_index) { + _pointers[_current_index] = _pointers[_current_size]; + } else { + _current_index = 0; + } + + return event_returned; + }; + + /** Return pointer to the first element that fulfills the passed in condition and remove the entry + * that was pointing to the item. Transfers ownership to caller. + * + * @param compare_func The condition that is checked for all the items. + * @return First element that fulfills the passed in condition or nullptr if no such item found. + */ + EventType* pop(mbed::Callback compare_func) + { + for (IndexType i = 0; i < _current_size ; ++i) { + if (compare_func(*_pointers[_current_index])) { + return pop(); + } + increment_current_index(); + } + + return nullptr; + } + + /** Return pointer to the first element that fulfills the passed in condition and remove the entry + * that was pointing to the item. Takes and returns number of failed matches allowing to speed up search. + * Transfers ownership to caller. + * + * @note Calls must be consecutive - any call to pop or find will invalidate the search. + * + * @param compare_func The condition that is checked for all the items. + * @param events_not_matching Pointer to the number of items already searched but not matching. + * This is updated in the method. + * @return First element that fulfills the passed in condition or nullptr if no such item found. + */ + EventType* continue_pop(mbed::Callback compare_func, IndexType *events_not_matching) + { + _current_index = *events_not_matching; + for (IndexType i = *events_not_matching; i < _current_size ; ++i) { + if (compare_func(*_pointers[_current_index])) { + return pop(); + } + (*events_not_matching)++; + increment_current_index(); + } + + return nullptr; + } + + /** Return pointer to the first element that fulfills the passed in condition. Does not remove item from list. + * + * @param compare_func The condition that is checked for all the items. + * @return First element that fulfills the passed in condition or nullptr if no such item found. + */ + EventType* find(mbed::Callback compare_func) + { + for (IndexType i = 0; i < _current_size ; ++i) { + if (compare_func(*_pointers[_current_index])) { + return _pointers[_current_index]; + } + increment_current_index(); + } + + return nullptr; + } + + /** Return number of events stored. + * + * @return Number of events stored. + */ + IndexType get_size() + { + return _current_size; + } + + private: + void increment_current_index() + { + _current_index++; + if (_current_index == _current_size) { + _current_index = 0; + } + } + + private: + EventType* _pointers[MAX_EVENTS]; + IndexType _current_size = 0; + /* this helps us find the event faster */ + IndexType _current_index = 0; + }; + private: /* Disallow copy and assignment. */ Gap(const Gap &); From f126793f2036a5a383dbedff823107aa14001fb1 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Tue, 22 Sep 2020 09:20:34 +0100 Subject: [PATCH 35/63] Add host reolustion for advertising and connections --- connectivity/FEATURE_BLE/mbed_lib.json | 5 + .../FEATURE_BLE/source/generic/GapImpl.cpp | 532 +++++++++++++----- .../FEATURE_BLE/source/generic/GapImpl.h | 97 ++++ 3 files changed, 484 insertions(+), 150 deletions(-) diff --git a/connectivity/FEATURE_BLE/mbed_lib.json b/connectivity/FEATURE_BLE/mbed_lib.json index 9c1a870e89..27b4fc0a7b 100644 --- a/connectivity/FEATURE_BLE/mbed_lib.json +++ b/connectivity/FEATURE_BLE/mbed_lib.json @@ -92,6 +92,11 @@ "help": "How many advertising sets the API can handle (this limits how much the stack can handle). Must be non-zero", "value": 15, "macro_name": "BLE_GAP_MAX_ADVERTISING_SETS" + }, + "ble-gap-max-advertising-reports-pending-address-resolution": { + "help": "How many advertising reports can be pending while awaiting private address resolution. This is only used if host privacy is enabled and controller privacy is disabled. Must be non-zero", + "value": 16, + "macro_name": "BLE_GAP_MAX_ADVERTISING_REPORTS_PENDING_ADDRESS_RESOLUTION" } } } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 789ec49eca..d02ca87f0d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1213,65 +1213,56 @@ void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) for (size_t i = 0; i < e.size(); ++i) { GapAdvertisingReportEvent::advertising_t advertising = e[i]; -#if BLE_FEATURE_PRIVACY - // Check if the address hasn't been resolved - if (_privacy_enabled && - _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && - advertising.address_type == connection_peer_address_type_t::RANDOM_ADDRESS && - is_random_private_resolvable_address(advertising.address.data()) - ) { - // FIXME: implement - // Filter it out - continue; - } -#endif // BLE_FEATURE_PRIVACY - // 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()); // report in new event handler - if (_event_handler) { - uint8_t event_type = 0; - - // Conversion table available at BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E - // 7.7.65.13 - switch (advertising.type.value()) { - case received_advertising_type_t::ADV_IND: - event_type = 0x13; - break; - case received_advertising_type_t::ADV_DIRECT_IND: - event_type = 0x15; - break; - case received_advertising_type_t::ADV_SCAN_IND: - event_type = 0x12; - break; - case received_advertising_type_t::ADV_NONCONN_IND: - event_type = 0x10; - break; - case received_advertising_type_t::SCAN_RESPONSE: - event_type = 0x1B; - break; - } - - _event_handler->onAdvertisingReport( - AdvertisingReportEvent( - advertising_event_t(event_type), - peer_address_type, - advertising.address, - /* primary */ phy_t::LE_1M, - /* secondary */ phy_t::NONE, - /* SID - NO ADI FIELD IN THE PDU */ 0xFF, - /* tx power information not available */ 127, - advertising.rssi, - /* NO PERIODIC ADVERTISING */ 0, - peer_address_type_t::ANONYMOUS, - ble::address_t(), - Span(advertising.data.data(), advertising.data.size()) - ) - ); + if (!_event_handler) { + continue; } + + uint8_t event_type = 0; + + // Conversion table available at BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E + // 7.7.65.13 + switch (advertising.type.value()) { + case received_advertising_type_t::ADV_IND: + event_type = 0x13; + break; + case received_advertising_type_t::ADV_DIRECT_IND: + event_type = 0x15; + break; + case received_advertising_type_t::ADV_SCAN_IND: + event_type = 0x12; + break; + case received_advertising_type_t::ADV_NONCONN_IND: + event_type = 0x10; + break; + case received_advertising_type_t::SCAN_RESPONSE: + event_type = 0x1B; + break; + } + + AdvertisingReportEvent event( + advertising_event_t(event_type), + peer_address_type, + advertising.address, + /* primary */ phy_t::LE_1M, + /* secondary */ phy_t::NONE, + /* SID - NO ADI FIELD IN THE PDU */ 0xFF, + /* tx power information not available */ 127, + advertising.rssi, + /* NO PERIODIC ADVERTISING */ 0, + peer_address_type_t::ANONYMOUS, + ble::address_t(), + Span(advertising.data.data(), advertising.data.size()) + ); + + signal_advertising_report( + event + ); } } @@ -1304,9 +1295,6 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) return; } - bool needs_pairing = false; - bool needs_authentication = false; - // There is no need to check for extending advertising availability as this // handler is for 4.x controllers if (e.role == connection_role_t::PERIPHERAL) { @@ -1314,44 +1302,6 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) } #if BLE_ROLE_PERIPHERAL -#if BLE_FEATURE_PRIVACY - if (_privacy_enabled && - e.role.value() == e.role.PERIPHERAL && - e.peer_address_type == peer_address_type_t::RANDOM - ) { - // Apply privacy policy if in peripheral mode for non-resolved addresses - ble::random_address_type_t random_address_type(ble::random_address_type_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 == ble::random_address_type_t::RESOLVABLE_PRIVATE) { - switch (_peripheral_privacy_configuration.resolution_strategy) { - case peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS: - // Reject connection request - the user will get notified through a callback - _pal_gap.disconnect( - e.connection_handle, - local_disconnection_reason_t::AUTHENTICATION_FAILURE - ); - return; - - case peripheral_privacy_configuration_t::PERFORM_PAIRING_PROCEDURE: - needs_pairing = true; - break; - - case peripheral_privacy_configuration_t::PERFORM_AUTHENTICATION_PROCEDURE: - needs_authentication = true; - break; - - default: - break; - } - } - } -#endif // BLE_FEATURE_PRIVACY - if (e.role.value() == e.role.PERIPHERAL) { _advertising_timeout.detach(); _pal_gap.advertising_enable(false); @@ -1379,34 +1329,23 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) // signal application if (_event_handler) { - _event_handler->onConnectionComplete( - ConnectionCompleteEvent( - BLE_ERROR_NONE, - e.connection_handle, - e.role, - e.peer_address_type, - e.peer_address, - e.local_resolvable_private_address, - e.peer_resolvable_private_address, - conn_interval_t(e.connection_interval), - e.connection_latency, - supervision_timeout_t(e.supervision_timeout), - /* default master clock accuracy */ ble::clock_accuracy_t::PPM_500 - ) + ConnectionCompleteEvent event( + BLE_ERROR_NONE, + e.connection_handle, + e.role, + e.peer_address_type, + e.peer_address, + e.local_resolvable_private_address, + e.peer_resolvable_private_address, + conn_interval_t(e.connection_interval), + e.connection_latency, + supervision_timeout_t(e.supervision_timeout), + /* default master clock accuracy */ ble::clock_accuracy_t::PPM_500 + ); + signal_connection_complete( + event ); } - -#if BLE_FEATURE_SECURITY - // Now starts pairing or authentication procedures if required - if (needs_pairing) { - ble::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 - } -#endif // BLE_FEATURE_SECURITY } @@ -2334,43 +2273,286 @@ void Gap::on_extended_advertising_report( const uint8_t *data ) { -#if BLE_FEATURE_PRIVACY - // Check if the address hasn't been resolved - if (_privacy_enabled && - _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && - address_type != nullptr && - *address_type == connection_peer_address_type_t::RANDOM_ADDRESS && - is_random_private_resolvable_address(address.data()) - ) { - // FIXME: Implement - return; - } -#endif // BLE_FEATURE_PRIVACY - if (!_event_handler) { return; } - _event_handler->onAdvertisingReport( - AdvertisingReportEvent( - event_type, - address_type ? - (peer_address_type_t::type) address_type->value() : - peer_address_type_t::ANONYMOUS, - (address_t &) address, - primary_phy, - secondary_phy ? *secondary_phy : phy_t::NONE, - advertising_sid, - tx_power, - rssi, - periodic_advertising_interval, - (ble::peer_address_type_t::type) direct_address_type.value(), - (address_t &) direct_address, - make_Span(data, data_length) - ) + peer_address_type_t peer_address_type = address_type ? (peer_address_type_t::type) address_type->value() + : peer_address_type_t::ANONYMOUS; + + AdvertisingReportEvent event( + event_type, + peer_address_type, + address, + primary_phy, + secondary_phy ? *secondary_phy : phy_t::NONE, + advertising_sid, + tx_power, + rssi, + periodic_advertising_interval, + (ble::peer_address_type_t::type) direct_address_type.value(), + (address_t &) direct_address, + make_Span(data, data_length) + ); + + signal_advertising_report( + event ); } +#if BLE_FEATURE_CONNECTABLE +void Gap::signal_connection_complete( + ConnectionCompleteEvent& event +) +{ +#if BLE_FEATURE_PRIVACY + bool address_resolved = false; + + /* if address resolution is not needed or already handled then the address is already resolved */ + if (!_privacy_enabled || + _address_registry.is_controller_privacy_supported() || + event.getPeerAddressType() == peer_address_type_t::PUBLIC || + !is_random_private_resolvable_address(event.getPeerAddress())) { + address_resolved = true; + } else { +#if BLE_ROLE_CENTRAL + if (event.getOwnRole() == connection_role_t::CENTRAL) { + if (_central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::DO_NOT_RESOLVE) { + address_resolved = true; + } + } +#endif BLE_ROLE_CENTRAL + +#if BLE_ROLE_PERIPHERAL + if (event.getOwnRole() == connection_role_t::PERIPHERAL) { + if (_peripheral_privacy_configuration.resolution_strategy == + peripheral_privacy_configuration_t::DO_NOT_RESOLVE) { + address_resolved = true; + } + } +#endif // BLE_ROLE_PERIPHERAL + } + + const address_t *peer_address; + target_peer_address_type_t peer_address_type(target_peer_address_type_t::RANDOM); + + /* first try to resolve synchronously in cache */ + if (!address_resolved) { + address_resolved = _address_registry.resolve_address_in_cache( + event.getPeerAddress(), + &peer_address_type, + &peer_address + ); + + if (address_resolved) { + conclude_signal_connection_complete_after_address_resolution( + event, + peer_address_type, + peer_address + ); + return; + } + } + + /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ + if (address_resolved) { + _event_handler->onConnectionComplete( + event + ); + } else { + bool resolution_pending = false; + ble_error_t ret = _address_registry.queue_resolve_address(event.getPeerAddress()); + + if (ret == BLE_ERROR_NONE) { + ConnectionCompleteEvent* event_copy = new(std::nothrow) ConnectionCompleteEvent(event); + if (!event_copy || !_connections_pending_address_resolution.push(event_copy)) { + delete event_copy; + } else { + resolution_pending = true; + } + } + + if (!resolution_pending) { + event.setStatus(BLE_ERROR_NO_MEM); + _event_handler->onConnectionComplete( + event + ); + _pal_gap.disconnect( + event.getConnectionHandle(), + local_disconnection_reason_t::LOW_RESOURCES + ); + } + } +#else + _event_handler->onConnectionComplete( + event + ); +#endif // BLE_FEATURE_PRIVACY +} + +#if BLE_FEATURE_PRIVACY +void Gap::conclude_signal_connection_complete_after_address_resolution( + ConnectionCompleteEvent &event, + target_peer_address_type_t identity_address_type, + const address_t *identity_address +) +{ +#if BLE_ROLE_PERIPHERAL + bool resolvable_address_not_known = false; +#endif // BLE_ROLE_PERIPHERAL + /* fix the event addresses */ + if (identity_address) { + /* move old address to resolvable address */ + event.setPeerResolvablePrivateAddress(event.getPeerAddress()); + event.setLocalResolvablePrivateAddress(_address_registry.get_resolvable_private_address()); + + event.setPeerAddress(*identity_address); + event.setPeerAddressType(identity_address_type == target_peer_address_type_t::RANDOM ? + peer_address_type_t::RANDOM_STATIC_IDENTITY + : peer_address_type_t::PUBLIC_IDENTITY); + } +#if BLE_ROLE_PERIPHERAL + if (!identity_address) { + if (_peripheral_privacy_configuration.resolution_strategy == + peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS) { + // Reject connection request - the user will get notified through a callback + _pal_gap.disconnect( + event.getConnectionHandle(), + local_disconnection_reason_t::AUTHENTICATION_FAILURE + ); + return; + } + resolvable_address_not_known = true; + } +#endif // BLE_ROLE_PERIPHERAL + + _event_handler->onConnectionComplete( + event + ); +#if BLE_ROLE_PERIPHERAL +#if BLE_FEATURE_SECURITY + if (resolvable_address_not_known) { + ble::SecurityManager &sm = BLE::Instance().securityManager(); + if (_peripheral_privacy_configuration.resolution_strategy == + peripheral_privacy_configuration_t::PERFORM_PAIRING_PROCEDURE) { + + // Request authentication to start pairing procedure + sm.requestAuthentication(event.getConnectionHandle()); + } else if (_peripheral_privacy_configuration.resolution_strategy == + peripheral_privacy_configuration_t::PERFORM_AUTHENTICATION_PROCEDURE) { + sm.setLinkSecurity( + event.getConnectionHandle(), + ble::SecurityManager::SecurityMode_t::SECURITY_MODE_ENCRYPTION_WITH_MITM + ); + } + } +#endif // BLE_FEATURE_SECURITY +#endif // BLE_ROLE_PERIPHERAL +} +#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_CONNECTABLE + +#if BLE_ROLE_OBSERVER +void Gap::signal_advertising_report( + AdvertisingReportEvent& event +) +{ +#if BLE_FEATURE_PRIVACY + bool address_resolved = false; + + /* if address resolution is not needed or already handled then the address is already resolved */ + if (!_privacy_enabled || + _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::DO_NOT_RESOLVE || + _address_registry.is_controller_privacy_supported() || + event.getPeerAddressType() == peer_address_type_t::PUBLIC || + !is_random_private_resolvable_address(event.getPeerAddress())) { + address_resolved = true; + } + + /* first try to resolve synchronously in cache */ + if (!address_resolved) { + const address_t *peer_address = nullptr; + target_peer_address_type_t peer_address_type(target_peer_address_type_t::RANDOM); + + address_resolved = _address_registry.resolve_address_in_cache( + event.getPeerAddress(), + &peer_address_type, + &peer_address + ); + + if (address_resolved) { + conclude_signal_advertising_report_after_address_resolution( + event, + peer_address_type, + peer_address + ); + return; + } + } + + /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ + if (address_resolved) { + _event_handler->onAdvertisingReport( + event + ); + } else { + /* check if there already is a RPA like that in the list of other pending reports */ + PendingAdvertisingReportEvent *duplicate_pending_event = _reports_pending_address_resolution.find( + [&event](PendingAdvertisingReportEvent& pending_event){ + return (pending_event.get_pending_event().getPeerAddress() == event.getPeerAddress()); + } + ); + + ble_error_t ret = BLE_ERROR_NONE; + + /* if there is already an item with the same address pending don't kick off resolution*/ + if (!duplicate_pending_event) { + ret = _address_registry.queue_resolve_address(event.getPeerAddress()); + } + + if (ret == BLE_ERROR_NONE) { + PendingAdvertisingReportEvent *pending_event = new(std::nothrow) PendingAdvertisingReportEvent(event); + + if (pending_event) { + if (!pending_event->is_valid() || !_reports_pending_address_resolution.push(pending_event)) { + delete pending_event; + } + } + } + } +#else + _event_handler->onAdvertisingReport( + event + ); +#endif // BLE_FEATURE_PRIVACY +} +#endif //BLE_ROLE_OBSERVER + +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_OBSERVER +void Gap::conclude_signal_advertising_report_after_address_resolution( + AdvertisingReportEvent &event, + target_peer_address_type_t identity_address_type, + const address_t *identity_address +) +{ + /* fix the report with the new address if there's an identity found */ + if (identity_address) { + /* filter out resolved address based on policy */ + if (_central_privacy_configuration.resolution_strategy == + central_privacy_configuration_t::RESOLVE_AND_FILTER) { + return; + } + event.setPeerAddress(*identity_address); + event.setPeerAddressType(identity_address_type == target_peer_address_type_t::RANDOM ? + peer_address_type_t::RANDOM_STATIC_IDENTITY + : peer_address_type_t::PUBLIC_IDENTITY); + } + + _event_handler->onAdvertisingReport(event); +} +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY void Gap::on_periodic_advertising_sync_established( hci_error_code_t error, @@ -2976,7 +3158,57 @@ void Gap::on_address_resolution_completed( const address_t &identity_address ) { - // FIXME: Implement +#if BLE_FEATURE_PRIVACY + if (!_event_handler || !_privacy_enabled) { + return; + } + +#if BLE_FEATURE_CONNECTABLE + ConnectionCompleteEvent* pending_connection_event = _connections_pending_address_resolution.pop( + [peer_resolvable_address](ConnectionCompleteEvent &event){ + return (event.getPeerAddress() == peer_resolvable_address); + } + ); + + if (pending_connection_event) { + /* move old address to resolvable address */ + conclude_signal_connection_complete_after_address_resolution( + *pending_connection_event, + identity_address_type, + resolved ? &identity_address : nullptr + ); + + delete pending_connection_event; + + /* we can return early, if there was a duplicate advertising report it will have its own resolution callback */ + return; + } +#endif //BLE_FEATURE_CONNECTABLE + +#if BLE_ROLE_OBSERVER + uint8_t items_searched = 0; + while(true) { + PendingAdvertisingReportEvent *event = _reports_pending_address_resolution.continue_pop( + [peer_resolvable_address](PendingAdvertisingReportEvent &event){ + return (event.get_pending_event().getPeerAddress() == peer_resolvable_address); + }, + &items_searched + ); + + if (!event) { + break; + } + + conclude_signal_advertising_report_after_address_resolution( + event->get_pending_event(), + identity_address_type, + resolved ? &identity_address : nullptr + ); + + delete event; + } +#endif BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index b5e7b8d2cb..2130773cf8 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -493,6 +493,44 @@ private: IndexType _current_index = 0; }; + class PendingAdvertisingReportEvent { + public: + PendingAdvertisingReportEvent( + const AdvertisingReportEvent& event_to_copy + ) : event(event_to_copy) + { + /* copy the data to the buffer */ + const mbed::Span payload = event_to_copy.getPayload(); + if (payload.size()) { + advertising_data_buffer = new(std::nothrow) uint8_t[payload.size()]; + if (advertising_data_buffer) { + memcpy(advertising_data_buffer, payload.data(), payload.size()); + /* set the payload to our local copy of the data */ + event.setAdvertisingData(mbed::make_Span(advertising_data_buffer, payload.size())); + } + } + }; + + ~PendingAdvertisingReportEvent() + { + delete[] advertising_data_buffer; + } + + bool is_valid() + { + return advertising_data_buffer || (event.getPayload().size() == 0); + } + + AdvertisingReportEvent& get_pending_event() + { + return event; + } + + private: + AdvertisingReportEvent event; + uint8_t *advertising_data_buffer = nullptr; + }; + private: /* Disallow copy and assignment. */ Gap(const Gap &); @@ -558,6 +596,50 @@ private: ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters); +#if BLE_FEATURE_CONNECTABLE + /** Pass the connection complete event to the application. This may involve privacy resolution. + * + * @param report Event to be passed to the user application. + */ + void signal_connection_complete(ConnectionCompleteEvent& report); + +#if BLE_FEATURE_PRIVACY + /** Pass the connection complete event to the application after privacy resolution completed. + * + * @param event Event to be passed to the user application. + * @param identity_address_type Address type of the identity address. + * @param identity_address Address resolved by private address resolution, nullptr if no identity found. + */ + void conclude_signal_connection_complete_after_address_resolution( + ConnectionCompleteEvent &event, + target_peer_address_type_t identity_address_type, + const address_t *identity_address + ); +#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_CONNECTABLE + +#if BLE_ROLE_OBSERVER + /** Pass the advertising report to the application. This may involve privacy resolution. + * + * @param report Report to be passed to the user application. + */ + void signal_advertising_report(AdvertisingReportEvent& report); + +#if BLE_FEATURE_PRIVACY + /** Pass the advertising report to the application after privacy resolution completed. + * + * @param event Event to be passed to the user application. + * @param identity_address_type Address type of the identity address. + * @param identity_address Address resolved by private address resolution, nullptr if no identity found. + */ + void conclude_signal_advertising_report_after_address_resolution( + AdvertisingReportEvent &event, + target_peer_address_type_t identity_address_type, + const address_t *identity_address + ); +#endif // BLE_FEATURE_PRIVACY +#endif // BLE_ROLE_OBSERVER + /* implements PalGap::EventHandler */ private: void on_read_phy( @@ -704,6 +786,15 @@ private: */ ble::Gap::EventHandler *_event_handler; +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_OBSERVER + EventList _reports_pending_address_resolution; +#endif // BLE_ROLE_OBSERVER +#if BLE_FEATURE_CONNECTABLE + EventList _connections_pending_address_resolution; +#endif // BLE_FEATURE_CONNECTABLE +#endif // BLE_FEATURE_PRIVACY + PalEventQueue &_event_queue; PalGap &_pal_gap; PalGenericAccessService &_gap_service; @@ -716,8 +807,14 @@ private: mutable whitelist_t _whitelist; bool _privacy_enabled; +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_PERIPHERAL peripheral_privacy_configuration_t _peripheral_privacy_configuration; +#endif // BLE_ROLE_PERIPHERAL +#if BLE_ROLE_OBSERVER central_privacy_configuration_t _central_privacy_configuration; +#endif //BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY ble::address_t _random_static_identity_address; From dee20fe5a707cfce8fce0484ba75753ccc012a12 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 11:00:07 +0100 Subject: [PATCH 36/63] BLE: Check if extended advertising is available to clear advertising set upon connection --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index d02ca87f0d..caa18c8366 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1295,9 +1295,7 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) return; } - // There is no need to check for extending advertising availability as this - // handler is for 4.x controllers - if (e.role == connection_role_t::PERIPHERAL) { + if (!is_extended_advertising_available() && e.role == connection_role_t::PERIPHERAL) { _active_sets.clear(LEGACY_ADVERTISING_HANDLE); } From 1daee237e913756a21fa9161eb7fdcd86230cc6c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 11:02:00 +0100 Subject: [PATCH 37/63] BLE: Queue address resolution in event queue to avoid synchronous execution Otherwise when no IRK are available, the process will execute synchronously, calling the callback before the return of the function. --- .../FEATURE_BLE/source/generic/PrivateAddressController.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index 1a9b938c92..9c8057d819 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -541,7 +541,10 @@ ble_error_t PrivateAddressController::queue_resolve_address(const address_t &pee return BLE_ERROR_NO_MEM; } - queue_privacy_control_block(cb); + _event_queue.post([this, cb] { + queue_privacy_control_block(cb); + }); + return BLE_ERROR_NONE; } From 3a632a3685adb004d071c91c2597675ebab8fa61 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 11:03:25 +0100 Subject: [PATCH 38/63] BLE: Check if the resolving list item is populated instead of IRK validity --- .../FEATURE_BLE/source/generic/PrivateAddressController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index 9c8057d819..d7ef1719b7 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -455,7 +455,7 @@ struct PrivateAddressController::PrivacyResolveAddress final : bool execute(PrivateAddressController& self) final { - if (self._resolving_list[resolving_list_index].peer_irk == irk_t{}) { + if (!self._resolving_list[resolving_list_index].populated) { // no entry at index 0, move to the next return start_next_resolution_round(self); } else { @@ -494,7 +494,7 @@ private: notify_completion(self, peer_address,false,nullptr); return true; } - } while (self._resolving_list[resolving_list_index].peer_irk != irk_t{}); + } while (!self._resolving_list[resolving_list_index].populated); start_resolution(self); return false; From 02667389db3219fe6fb98fd7a5ba8dccc75d2ab5 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 11:04:39 +0100 Subject: [PATCH 39/63] BLE: Fix insertion to host resolving list. --- .../generic/PrivateAddressController.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index d7ef1719b7..ea3837ed95 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -164,16 +164,34 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list( peer_irk ); } else { + // ensure an entry is not added twice + for (auto &entry : _resolving_list) { + if (entry.populated && + entry.peer_address_type == peer_address_type && + entry.peer_address == peer_identity_address && + entry.peer_irk == peer_irk + ) { + return BLE_ERROR_NONE; + } + } + + bool entry_added = false; for (auto &entry : _resolving_list) { if (entry.populated == false) { entry.peer_address_type = peer_address_type; entry.peer_address = peer_identity_address; entry.peer_irk = peer_irk; entry.populated = true; - return BLE_ERROR_NONE; + entry_added = true; + break; } } + if (!entry_added) { + return BLE_ERROR_NO_MEM; + } + + // Remove unresolved entries from the resolved list remove_resolution_entry_from_cache( [&](resolution_entry_t &entry) { From 7c8a75466771c4616306e981475344fdb60ff828 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 15:05:21 +0100 Subject: [PATCH 40/63] BLE: Remove set advertising timeout from SM pal --- .../source/cordio/source/PalSecurityManagerImpl.cpp | 12 ------------ .../source/cordio/source/PalSecurityManagerImpl.h | 9 --------- .../source/generic/SecurityManagerImpl.cpp | 5 ++++- .../FEATURE_BLE/source/pal/PalSecurityManager.h | 8 -------- 4 files changed, 4 insertions(+), 30 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp index 993bb4d482..42c8b668fe 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp @@ -207,18 +207,6 @@ ble_error_t PalSecurityManager::encrypt_data( return BLE_ERROR_NOT_IMPLEMENTED; } -//////////////////////////////////////////////////////////////////////////// -// Privacy -// - - -ble_error_t PalSecurityManager::set_private_address_timeout( - uint16_t timeout_in_seconds -) -{ - DmPrivSetResolvablePrivateAddrTimeout(timeout_in_seconds); - return BLE_ERROR_NONE; -} //////////////////////////////////////////////////////////////////////////// // Keys diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h index e38e37431e..7f0100610c 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.h @@ -174,15 +174,6 @@ public: encryption_block_t &data ) final; - //////////////////////////////////////////////////////////////////////////// - // Privacy - // - - /** - * @see ::ble::PalSecurityManager::set_private_address_timeout - */ - ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds) final; - //////////////////////////////////////////////////////////////////////////// // Keys // diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index 3f3427e8d5..787862fc5e 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -743,7 +743,10 @@ ble_error_t SecurityManager::getSigningKey(connection_handle_t connection, bool ble_error_t SecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; - return _pal.set_private_address_timeout(timeout_in_seconds); + _private_address_controller.set_timeout( + resolvable_address_timeout_t(timeout_in_seconds) + ); + return BLE_ERROR_NONE; } //////////////////////////////////////////////////////////////////////////// diff --git a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h index 99caec6d8e..6f01fd7a20 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h +++ b/connectivity/FEATURE_BLE/source/pal/PalSecurityManager.h @@ -753,14 +753,6 @@ public: encryption_block_t &data ) = 0; - //////////////////////////////////////////////////////////////////////////// - // Privacy - // - - virtual ble_error_t set_private_address_timeout( - uint16_t timeout_in_seconds - ) = 0; - //////////////////////////////////////////////////////////////////////////// // Keys // From 4c1afe8e83a2295888cb2b4153a8e4d8dd1d6ccb Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 15:06:24 +0100 Subject: [PATCH 41/63] BLE: Update identity address when retrieved from the DB --- .../source/generic/SecurityManagerImpl.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index 787862fc5e..e7a547bd4b 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -1038,8 +1038,12 @@ ble_error_t SecurityManager::init_identity() ble::Gap& gap = BLE::Instance().gap(); irk_t irk = _db->get_local_irk(); + address_t identity_address; + bool public_identity_address = false; if (irk != irk_t()) { pirk = &irk; + public_identity_address = _db->is_local_identity_address_public(); + identity_address = _db->get_local_identity_address(); if (!_db->is_local_identity_address_public()) { // Some controllers doesn't store their random static address and @@ -1060,16 +1064,15 @@ ble_error_t SecurityManager::init_identity() } pirk = &irk; - address_t random_static_address = gap.getRandomStaticAddress(); - if (ret != BLE_ERROR_NONE) { - return ret; - } - _db->set_local_identity(irk, random_static_address, /* public_address */ false); + public_identity_address = false; + identity_address = gap.getRandomStaticAddress(); + _db->set_local_identity(irk, identity_address, public_identity_address); } auto err = _pal.set_irk(*pirk); if (!err) { _private_address_controller.set_local_irk(*pirk); + _pal.set_identity_address(identity_address, public_identity_address); } return err; } From 8716298ea22c4425b40d160f44dc5a0546576003 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 17:37:56 +0100 Subject: [PATCH 42/63] BLE: Update DB entry if current entry doesn't match requested EDIV and RAND --- .../FEATURE_BLE/source/generic/SecurityDb.h | 58 +++++++++++++++++-- .../source/generic/SecurityManagerImpl.cpp | 2 +- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityDb.h b/connectivity/FEATURE_BLE/source/generic/SecurityDb.h index 3cf01f35f4..8854858334 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityDb.h +++ b/connectivity/FEATURE_BLE/source/generic/SecurityDb.h @@ -168,16 +168,26 @@ public: */ virtual void get_entry_local_keys( SecurityEntryKeysDbCb_t cb, - entry_handle_t db_handle, + entry_handle_t* db_handle, const ediv_t &ediv, const rand_t &rand ) { - SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + 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); + cb(*db_handle, keys); } else { - cb(db_handle, NULL); + // Maybe this isn't the correct entry, try to find one that matches + entry_handle_t correct_handle = find_entry_by_peer_ediv_rand(ediv, rand); + if (!correct_handle) { + cb(*db_handle, NULL); + } + // Note: keys should never be null as a matching entry has been retrieved + SecurityEntryKeys_t* keys = read_in_entry_local_keys(correct_handle); + MBED_ASSERT(keys); + close_entry(*db_handle, false); + *db_handle = correct_handle; + cb(*db_handle, keys); } } @@ -552,17 +562,53 @@ public: return nullptr; } + /** + * Find a database entry based on ediv and rand. + * + * @param[in] ediv E diversifier + * @param[in] rand random part + * + * @return A handle to the entry. + */ + virtual entry_handle_t find_entry_by_peer_ediv_rand( + const ediv_t &ediv, + const rand_t &rand + ) { + 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) { + continue; + } + + SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle); + if (!keys) { + continue; + } + + if (keys->ediv == ediv && keys->rand == rand) { + return db_handle; + } + } + + return nullptr; + } + + /** * Close a connection entry. * * @param[in] db_handle this handle will be freed up from the security db. */ - virtual void close_entry(entry_handle_t db_handle) { + virtual void close_entry(entry_handle_t db_handle, bool require_sync = true) { SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle); if (flags) { flags->connected = false; } - sync(db_handle); + if (require_sync) { + sync(db_handle); + } } /** diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index e7a547bd4b..02db71a9ad 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -1935,7 +1935,7 @@ void SecurityManager::on_ltk_request( _db->get_entry_local_keys( mbed::callback(this, &SecurityManager::set_ltk_cb), - cb->db_entry, + &cb->db_entry, ediv, rand ); From 8fe2d7ebbec56eaf4ee9764a78f1b58380b2881e Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 23 Sep 2020 17:38:58 +0100 Subject: [PATCH 43/63] BLE: Report connection internally when address resolution has completed. --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 90 ++++++++++--------- .../FEATURE_BLE/source/generic/GapImpl.h | 7 ++ 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index caa18c8366..fce36a26ff 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1306,43 +1306,24 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) } #endif // BLE_ROLE_PERIPHERAL - ble::address_t address; - if (_address_type == own_address_type_t::PUBLIC) { - address = _pal_gap.get_device_address(); - } else { - address = _pal_gap.get_random_address(); - } + ConnectionCompleteEvent event( + BLE_ERROR_NONE, + e.connection_handle, + e.role, + e.peer_address_type, + e.peer_address, + e.local_resolvable_private_address, + e.peer_resolvable_private_address, + conn_interval_t(e.connection_interval), + e.connection_latency, + supervision_timeout_t(e.supervision_timeout), + /* default master clock accuracy */ ble::clock_accuracy_t::PPM_500 + ); - // signal internal stack - if (_connection_event_handler) { - _connection_event_handler->on_connected( - e.connection_handle, - e.role, - e.peer_address_type, - e.peer_address, - _address_type, - address - ); - } - - // signal application if (_event_handler) { - ConnectionCompleteEvent event( - BLE_ERROR_NONE, - e.connection_handle, - e.role, - e.peer_address_type, - e.peer_address, - e.local_resolvable_private_address, - e.peer_resolvable_private_address, - conn_interval_t(e.connection_interval), - e.connection_latency, - supervision_timeout_t(e.supervision_timeout), - /* default master clock accuracy */ ble::clock_accuracy_t::PPM_500 - ); - signal_connection_complete( - event - ); + signal_connection_complete(event); + } else { + report_internal_connection_complete(event); } } @@ -2299,6 +2280,30 @@ void Gap::on_extended_advertising_report( } #if BLE_FEATURE_CONNECTABLE +void Gap::report_internal_connection_complete(const ConnectionCompleteEvent& event) +{ + if (!_connection_event_handler || event.getStatus() != BLE_ERROR_NONE) { + return; + } + + ble::address_t address; + if (_address_type == own_address_type_t::PUBLIC) { + address = _pal_gap.get_device_address(); + } else { + address = _pal_gap.get_random_address(); + } + + _connection_event_handler->on_connected( + event.getConnectionHandle(), + event.getOwnRole(), + event.getPeerAddressType(), + event.getPeerAddress(), + _address_type, + address + ); +} + + void Gap::signal_connection_complete( ConnectionCompleteEvent& event ) @@ -2354,9 +2359,8 @@ void Gap::signal_connection_complete( /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ if (address_resolved) { - _event_handler->onConnectionComplete( - event - ); + report_internal_connection_complete(event); + _event_handler->onConnectionComplete(event); } else { bool resolution_pending = false; ble_error_t ret = _address_registry.queue_resolve_address(event.getPeerAddress()); @@ -2382,9 +2386,8 @@ void Gap::signal_connection_complete( } } #else - _event_handler->onConnectionComplete( - event - ); + report_internal_connection_complete(event); + _event_handler->onConnectionComplete(event); #endif // BLE_FEATURE_PRIVACY } @@ -2424,9 +2427,8 @@ void Gap::conclude_signal_connection_complete_after_address_resolution( } #endif // BLE_ROLE_PERIPHERAL - _event_handler->onConnectionComplete( - event - ); + report_internal_connection_complete(event); + _event_handler->onConnectionComplete(event); #if BLE_ROLE_PERIPHERAL #if BLE_FEATURE_SECURITY if (resolvable_address_not_known) { diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 2130773cf8..c9407d05da 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -597,6 +597,13 @@ private: ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters); #if BLE_FEATURE_CONNECTABLE + /** Call the internal handlers that report to the security manager and GATT + * that a connection has been established. + * + * @param report Connection event + */ + void report_internal_connection_complete(const ConnectionCompleteEvent& report); + /** Pass the connection complete event to the application. This may involve privacy resolution. * * @param report Event to be passed to the user application. From e4b317c1b111fdbb6b8edbdea5529b7319cf7c87 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 25 Sep 2020 16:20:40 +0100 Subject: [PATCH 44/63] BLE: Add workaround for cordio use of global random address In Cordio, the global random address is used when the local device is connected instead of the advertising set one. This can cause pairing to fail if the advertising set address and the global random address are different. This workaround forces the global random address to be set when advertising is started and extended advertising is present. --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index fce36a26ff..d2a235ca44 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -33,6 +33,9 @@ #include "source/pal/PalSecurityManager.h" +// Cordio defines the random address used by connection to be the global one +#define CORDIO_GLOBAL_RANDOM_ADDRESS_FOR_CONNECTION 1 + using namespace std::chrono; MBED_STATIC_ASSERT(BLE_GAP_MAX_ADVERTISING_SETS < 0xFF, "BLE_GAP_MAX_ADVERTISING_SETS must be less than 255"); @@ -1928,6 +1931,9 @@ ble_error_t Gap::startAdvertising( if (is_extended_advertising_available()) { // Addresses can be updated if the set is not advertising if (!_active_sets.get(handle)) { +#if CORDIO_GLOBAL_RANDOM_ADDRESS_FOR_CONNECTION + _pal_gap.set_random_address(*random_address); +#endif _pal_gap.set_advertising_set_random_address(handle, *random_address); } @@ -2324,7 +2330,7 @@ void Gap::signal_connection_complete( address_resolved = true; } } -#endif BLE_ROLE_CENTRAL +#endif #if BLE_ROLE_PERIPHERAL if (event.getOwnRole() == connection_role_t::PERIPHERAL) { @@ -3207,7 +3213,7 @@ void Gap::on_address_resolution_completed( delete event; } -#endif BLE_ROLE_OBSERVER +#endif // BLE_ROLE_OBSERVER #endif // BLE_FEATURE_PRIVACY } @@ -3264,6 +3270,7 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ bool advertising_use_main_address = true; // Extended advertising is a special case as the address isn't shared with // the main address. +#if !CORDIO_GLOBAL_RANDOM_ADDRESS_FOR_CONNECTION #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { if (operation == controller_operation_t::advertising) { @@ -3277,6 +3284,8 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ } } #endif +#endif + // For other cases we first compute the address being used and then compares // it to the address to use to determine if the address is correct or not. From 76f89f6f89bf4ab15b7268d099c0fc2ad382245a Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 25 Sep 2020 17:22:16 +0100 Subject: [PATCH 45/63] BLE: Factorize peripheral privacy applied when connected --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 93 ++++++++++++------- .../FEATURE_BLE/source/generic/GapImpl.h | 10 ++ 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index d2a235ca44..51c739b7ec 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2365,6 +2365,9 @@ void Gap::signal_connection_complete( /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ if (address_resolved) { + if (!apply_peripheral_privacy_connection_policy(event)) { + return; + } report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); } else { @@ -2398,15 +2401,64 @@ void Gap::signal_connection_complete( } #if BLE_FEATURE_PRIVACY + +bool Gap::apply_peripheral_privacy_connection_policy( + const ConnectionCompleteEvent &event +) +{ +#if BLE_ROLE_PERIPHERAL + if (event.getOwnRole() != connection_role_t::PERIPHERAL) { + return true; + } + + if (event.getPeerAddressType() != peer_address_type_t::RANDOM) { + return true; + } + + if (!is_random_private_resolvable_address(event.getPeerAddress())) { + return true; + } + + auto connection_handle = event.getConnectionHandle(); + + switch (_peripheral_privacy_configuration.resolution_strategy) { + case peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS: + _pal_gap.disconnect( + connection_handle, + local_disconnection_reason_t::AUTHENTICATION_FAILURE + ); + return false; + + case peripheral_privacy_configuration_t::PERFORM_PAIRING_PROCEDURE: + _event_queue.post([connection_handle] { + BLE::Instance().securityManager().requestAuthentication(connection_handle); + }); + return true; + + case peripheral_privacy_configuration_t::PERFORM_AUTHENTICATION_PROCEDURE: + _event_queue.post([connection_handle] { + BLE::Instance().securityManager().setLinkSecurity( + connection_handle, + ble::SecurityManager::SecurityMode_t::SECURITY_MODE_ENCRYPTION_WITH_MITM + ); + }); + return true; + + default: + return true; + } +#else + return true; +#endif +} + + void Gap::conclude_signal_connection_complete_after_address_resolution( ConnectionCompleteEvent &event, target_peer_address_type_t identity_address_type, const address_t *identity_address ) { -#if BLE_ROLE_PERIPHERAL - bool resolvable_address_not_known = false; -#endif // BLE_ROLE_PERIPHERAL /* fix the event addresses */ if (identity_address) { /* move old address to resolvable address */ @@ -2418,42 +2470,13 @@ void Gap::conclude_signal_connection_complete_after_address_resolution( peer_address_type_t::RANDOM_STATIC_IDENTITY : peer_address_type_t::PUBLIC_IDENTITY); } -#if BLE_ROLE_PERIPHERAL - if (!identity_address) { - if (_peripheral_privacy_configuration.resolution_strategy == - peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS) { - // Reject connection request - the user will get notified through a callback - _pal_gap.disconnect( - event.getConnectionHandle(), - local_disconnection_reason_t::AUTHENTICATION_FAILURE - ); - return; - } - resolvable_address_not_known = true; + + if (!apply_peripheral_privacy_connection_policy(event)) { + return; } -#endif // BLE_ROLE_PERIPHERAL report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); -#if BLE_ROLE_PERIPHERAL -#if BLE_FEATURE_SECURITY - if (resolvable_address_not_known) { - ble::SecurityManager &sm = BLE::Instance().securityManager(); - if (_peripheral_privacy_configuration.resolution_strategy == - peripheral_privacy_configuration_t::PERFORM_PAIRING_PROCEDURE) { - - // Request authentication to start pairing procedure - sm.requestAuthentication(event.getConnectionHandle()); - } else if (_peripheral_privacy_configuration.resolution_strategy == - peripheral_privacy_configuration_t::PERFORM_AUTHENTICATION_PROCEDURE) { - sm.setLinkSecurity( - event.getConnectionHandle(), - ble::SecurityManager::SecurityMode_t::SECURITY_MODE_ENCRYPTION_WITH_MITM - ); - } - } -#endif // BLE_FEATURE_SECURITY -#endif // BLE_ROLE_PERIPHERAL } #endif // BLE_FEATURE_PRIVACY #endif // BLE_FEATURE_CONNECTABLE diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index c9407d05da..46b8f5ff6e 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -611,6 +611,16 @@ private: void signal_connection_complete(ConnectionCompleteEvent& report); #if BLE_FEATURE_PRIVACY + /** + * Apply the privacy policies when the local peripheral is connected. + * @param event The connection event + * @return true if the policy process has been successful and false if the + * it fails meaning the process connection shouldn't continue. + */ + bool apply_peripheral_privacy_connection_policy( + const ConnectionCompleteEvent &event + ); + /** Pass the connection complete event to the application after privacy resolution completed. * * @param event Event to be passed to the user application. From 03cc0f99403cd4fc7f5e610408ed61aaa36d53e4 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Thu, 24 Sep 2020 17:25:53 +0100 Subject: [PATCH 46/63] host privacy config option to enable it --- .../FEATURE_BLE/include/ble/gap/Types.h | 4 +- connectivity/FEATURE_BLE/mbed_lib.json | 10 + connectivity/FEATURE_BLE/source/Gap.cpp | 4 +- .../PalPrivateAddressControllerImpl.cpp | 4 +- .../FEATURE_BLE/source/generic/GapImpl.cpp | 49 +++-- .../FEATURE_BLE/source/generic/GapImpl.h | 19 +- .../generic/PrivateAddressController.cpp | 194 ++++++++++-------- .../source/generic/PrivateAddressController.h | 39 ++-- .../source/pal/PalPrivateAddressController.h | 2 + 9 files changed, 192 insertions(+), 133 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/gap/Types.h b/connectivity/FEATURE_BLE/include/ble/gap/Types.h index 6049746940..0b2d1a4f9f 100644 --- a/connectivity/FEATURE_BLE/include/ble/gap/Types.h +++ b/connectivity/FEATURE_BLE/include/ble/gap/Types.h @@ -455,8 +455,8 @@ struct scanning_filter_policy_t : SafeEnum { NO_FILTER = 0x00, /** - * Accept only advertising packets from devices in the whitelist except - * directed advertising packets not addressed to this device. + * Accept only advertising packets from devices in the whitelist. + * Directed advertising packets not addressed to this device will be ignored. */ FILTER_ADVERTISING = 0x01, diff --git a/connectivity/FEATURE_BLE/mbed_lib.json b/connectivity/FEATURE_BLE/mbed_lib.json index 27b4fc0a7b..f7cefee640 100644 --- a/connectivity/FEATURE_BLE/mbed_lib.json +++ b/connectivity/FEATURE_BLE/mbed_lib.json @@ -93,10 +93,20 @@ "value": 15, "macro_name": "BLE_GAP_MAX_ADVERTISING_SETS" }, + "ble-gap-host-based-private-address-resolution": { + "help": "Perform address resolution on the host, not the controller. Controller based privacy is preferred as it happens lower down the stack but this can be used in case controller based privacy is unavailable. If this is enabled the controller will not be used for privacy.", + "value": true, + "macro_name": "BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION" + }, "ble-gap-max-advertising-reports-pending-address-resolution": { "help": "How many advertising reports can be pending while awaiting private address resolution. This is only used if host privacy is enabled and controller privacy is disabled. Must be non-zero", "value": 16, "macro_name": "BLE_GAP_MAX_ADVERTISING_REPORTS_PENDING_ADDRESS_RESOLUTION" + }, + "ble-gap-host-privacy-resolved-cache-size": { + "help": "Used for host privacy. How many last resolved addresses to store to speed up resolution. This is especially valuable for resolving advertising which creates repeated queries for the same address.", + "value": 16, + "macro_name": "BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE" } } } diff --git a/connectivity/FEATURE_BLE/source/Gap.cpp b/connectivity/FEATURE_BLE/source/Gap.cpp index b45031807f..5fa3b992db 100644 --- a/connectivity/FEATURE_BLE/source/Gap.cpp +++ b/connectivity/FEATURE_BLE/source/Gap.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -506,4 +506,4 @@ ble::address_t Gap::getRandomStaticAddress() return impl->getRandomStaticAddress(); } -} // namespace ble \ No newline at end of file +} // namespace ble diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp index 2bc49b2ad7..1e87e37938 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -193,6 +193,7 @@ bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg) return true; } +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION case DM_PRIV_RESOLVED_ADDR_IND: { instance()._resolving_rpa = false; @@ -203,6 +204,7 @@ bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg) handler->on_private_address_resolved(msg->status == HCI_SUCCESS); return true; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION 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 diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 51c739b7ec..6cdbf2414c 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -929,9 +929,11 @@ ble_error_t Gap::enablePrivacy(bool enable) _address_registry.stop_private_address_generation(); } +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (_address_registry.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } +#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION return BLE_ERROR_NONE; } @@ -946,9 +948,11 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( { _peripheral_privacy_configuration = *configuration; +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (_address_registry.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } +#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION return BLE_ERROR_NONE; } @@ -978,9 +982,11 @@ ble_error_t Gap::setCentralPrivacyConfiguration( { _central_privacy_configuration = *configuration; +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (_address_registry.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } +#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION return BLE_ERROR_NONE; } @@ -1474,7 +1480,7 @@ bool Gap::initialize_whitelist() const return true; } - +#if BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t Gap::update_ll_address_resolution_setting() { // enable if privacy is enabled and resolution is requested in either central or peripheral mode @@ -1496,6 +1502,7 @@ ble_error_t Gap::update_ll_address_resolution_setting() return _address_registry.enable_controller_address_resolution(enable); } +#endif // BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #if BLE_ROLE_BROADCASTER uint8_t Gap::getMaxAdvertisingSetNumber() @@ -2314,12 +2321,11 @@ void Gap::signal_connection_complete( ConnectionCompleteEvent& event ) { -#if BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION bool address_resolved = false; /* if address resolution is not needed or already handled then the address is already resolved */ if (!_privacy_enabled || - _address_registry.is_controller_privacy_supported() || event.getPeerAddressType() == peer_address_type_t::PUBLIC || !is_random_private_resolvable_address(event.getPeerAddress())) { address_resolved = true; @@ -2330,7 +2336,7 @@ void Gap::signal_connection_complete( address_resolved = true; } } -#endif +#endif // BLE_ROLE_CENTRAL #if BLE_ROLE_PERIPHERAL if (event.getOwnRole() == connection_role_t::PERIPHERAL) { @@ -2347,7 +2353,7 @@ void Gap::signal_connection_complete( /* first try to resolve synchronously in cache */ if (!address_resolved) { - address_resolved = _address_registry.resolve_address_in_cache( + address_resolved = _address_registry.resolve_address_in_host_cache( event.getPeerAddress(), &peer_address_type, &peer_address @@ -2372,7 +2378,7 @@ void Gap::signal_connection_complete( _event_handler->onConnectionComplete(event); } else { bool resolution_pending = false; - ble_error_t ret = _address_registry.queue_resolve_address(event.getPeerAddress()); + ble_error_t ret = _address_registry.queue_resolve_address_on_host(event.getPeerAddress()); if (ret == BLE_ERROR_NONE) { ConnectionCompleteEvent* event_copy = new(std::nothrow) ConnectionCompleteEvent(event); @@ -2397,11 +2403,10 @@ void Gap::signal_connection_complete( #else report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } #if BLE_FEATURE_PRIVACY - bool Gap::apply_peripheral_privacy_connection_policy( const ConnectionCompleteEvent &event ) @@ -2451,8 +2456,9 @@ bool Gap::apply_peripheral_privacy_connection_policy( return true; #endif } +#endif // BLE_FEATURE_PRIVACY - +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::conclude_signal_connection_complete_after_address_resolution( ConnectionCompleteEvent &event, target_peer_address_type_t identity_address_type, @@ -2478,7 +2484,7 @@ void Gap::conclude_signal_connection_complete_after_address_resolution( report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); } -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #endif // BLE_FEATURE_CONNECTABLE #if BLE_ROLE_OBSERVER @@ -2486,13 +2492,12 @@ void Gap::signal_advertising_report( AdvertisingReportEvent& event ) { -#if BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION bool address_resolved = false; /* if address resolution is not needed or already handled then the address is already resolved */ if (!_privacy_enabled || _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::DO_NOT_RESOLVE || - _address_registry.is_controller_privacy_supported() || event.getPeerAddressType() == peer_address_type_t::PUBLIC || !is_random_private_resolvable_address(event.getPeerAddress())) { address_resolved = true; @@ -2503,7 +2508,7 @@ void Gap::signal_advertising_report( const address_t *peer_address = nullptr; target_peer_address_type_t peer_address_type(target_peer_address_type_t::RANDOM); - address_resolved = _address_registry.resolve_address_in_cache( + address_resolved = _address_registry.resolve_address_in_host_cache( event.getPeerAddress(), &peer_address_type, &peer_address @@ -2536,7 +2541,7 @@ void Gap::signal_advertising_report( /* if there is already an item with the same address pending don't kick off resolution*/ if (!duplicate_pending_event) { - ret = _address_registry.queue_resolve_address(event.getPeerAddress()); + ret = _address_registry.queue_resolve_address_on_host(event.getPeerAddress()); } if (ret == BLE_ERROR_NONE) { @@ -2553,11 +2558,11 @@ void Gap::signal_advertising_report( _event_handler->onAdvertisingReport( event ); -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } #endif //BLE_ROLE_OBSERVER -#if BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #if BLE_ROLE_OBSERVER void Gap::conclude_signal_advertising_report_after_address_resolution( AdvertisingReportEvent &event, @@ -2581,7 +2586,7 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( _event_handler->onAdvertisingReport(event); } #endif // BLE_ROLE_OBSERVER -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::on_periodic_advertising_sync_established( hci_error_code_t error, @@ -3179,7 +3184,8 @@ void Gap::on_private_address_generated(bool connectable) } } - +#if BLE_FEATURE_PRIVACY +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, @@ -3187,7 +3193,6 @@ void Gap::on_address_resolution_completed( const address_t &identity_address ) { -#if BLE_FEATURE_PRIVACY if (!_event_handler || !_privacy_enabled) { return; } @@ -3237,9 +3242,9 @@ void Gap::on_address_resolution_completed( delete event; } #endif // BLE_ROLE_OBSERVER -#endif // BLE_FEATURE_PRIVACY } - +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_FEATURE_PRIVACY bool Gap::is_advertising() const { @@ -3297,7 +3302,7 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { if (operation == controller_operation_t::advertising) { - if (_set_is_connectable.get(set_id) == false && peripheral_non_resolvable) { + if (!_set_is_connectable.get(set_id) && peripheral_non_resolvable) { return &non_resolvable_address; } else { return &resolvable_address; diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 46b8f5ff6e..c0ab2a9063 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -493,6 +493,7 @@ private: IndexType _current_index = 0; }; +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION class PendingAdvertisingReportEvent { public: PendingAdvertisingReportEvent( @@ -530,6 +531,7 @@ private: AdvertisingReportEvent event; uint8_t *advertising_data_buffer = nullptr; }; +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION private: /* Disallow copy and assignment. */ @@ -585,7 +587,9 @@ private: bool initialize_whitelist() const; +#if BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t update_ll_address_resolution_setting(); +#endif // BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t setExtendedAdvertisingParameters( advertising_handle_t handle, @@ -620,7 +624,9 @@ private: bool apply_peripheral_privacy_connection_policy( const ConnectionCompleteEvent &event ); +#endif // BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** Pass the connection complete event to the application after privacy resolution completed. * * @param event Event to be passed to the user application. @@ -632,7 +638,7 @@ private: target_peer_address_type_t identity_address_type, const address_t *identity_address ); -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #endif // BLE_FEATURE_CONNECTABLE #if BLE_ROLE_OBSERVER @@ -642,7 +648,7 @@ private: */ void signal_advertising_report(AdvertisingReportEvent& report); -#if BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** Pass the advertising report to the application after privacy resolution completed. * * @param event Event to be passed to the user application. @@ -654,7 +660,7 @@ private: target_peer_address_type_t identity_address_type, const address_t *identity_address ); -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #endif // BLE_ROLE_OBSERVER /* implements PalGap::EventHandler */ @@ -767,13 +773,14 @@ private: void on_non_resolvable_private_addresses_generated(const address_t &address) final; void on_private_address_generated(bool connectable); - +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, target_peer_address_type_t identity_address_type, const address_t &identity_address ) final; +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION private: bool is_advertising() const; @@ -803,14 +810,14 @@ private: */ ble::Gap::EventHandler *_event_handler; -#if BLE_FEATURE_PRIVACY +#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION #if BLE_ROLE_OBSERVER EventList _reports_pending_address_resolution; #endif // BLE_ROLE_OBSERVER #if BLE_FEATURE_CONNECTABLE EventList _connections_pending_address_resolution; #endif // BLE_FEATURE_CONNECTABLE -#endif // BLE_FEATURE_PRIVACY +#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION PalEventQueue &_event_queue; PalGap &_pal_gap; diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index ea3837ed95..31638ad1fb 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -31,11 +31,13 @@ PrivateAddressController::PrivateAddressController( _pal.initialize(); _pal.set_event_handler(this); +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION auto** next = &_free_resolution_entries; for (auto &entry : _resolution_list) { *next = &entry; next = &entry.next; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } PrivateAddressController::~PrivateAddressController() @@ -132,19 +134,25 @@ bool PrivateAddressController::is_controller_privacy_supported() return _pal.is_ll_privacy_supported(); } +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t PrivateAddressController::enable_controller_address_resolution(bool enable) { MBED_ASSERT(is_controller_privacy_supported()); return _pal.set_ll_address_resolution(enable); } +#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION uint8_t PrivateAddressController::read_resolving_list_capacity() { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + return BLE_SECURITY_DATABASE_MAX_ENTRIES; +#else if (is_controller_privacy_supported()) { return _pal.read_resolving_list_capacity(); } else { - return RESOLVING_LIST_SIZE; + return 0; } +#endif //BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } ble_error_t PrivateAddressController::add_device_to_resolving_list( @@ -157,6 +165,47 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list( return BLE_ERROR_INVALID_STATE; } +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + // ensure an entry is not added twice + for (auto &entry : _resolving_list) { + if (entry.populated && + entry.peer_address_type == peer_address_type && + entry.peer_address == peer_identity_address && + entry.peer_irk == peer_irk + ) { + return BLE_ERROR_NONE; + } + } + + bool entry_added = false; + for (auto &entry : _resolving_list) { + if (entry.populated == false) { + entry.peer_address_type = peer_address_type; + entry.peer_address = peer_identity_address; + entry.peer_irk = peer_irk; + entry.populated = true; + entry_added = true; + break; + } + } + + if (!entry_added) { + return BLE_ERROR_NO_MEM; + } + + + // Remove unresolved entries from the resolved list + remove_resolution_entry_from_cache( + [&](resolution_entry_t &entry) { + return entry.identity == nullptr; + } + ); + + // reset pending resolution request + restart_resolution_process_on_host(); + + return BLE_ERROR_NO_MEM; +#else if (is_controller_privacy_supported()) { return queue_add_device_to_resolving_list( peer_address_type, @@ -164,46 +213,9 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list( peer_irk ); } else { - // ensure an entry is not added twice - for (auto &entry : _resolving_list) { - if (entry.populated && - entry.peer_address_type == peer_address_type && - entry.peer_address == peer_identity_address && - entry.peer_irk == peer_irk - ) { - return BLE_ERROR_NONE; - } - } - - bool entry_added = false; - for (auto &entry : _resolving_list) { - if (entry.populated == false) { - entry.peer_address_type = peer_address_type; - entry.peer_address = peer_identity_address; - entry.peer_irk = peer_irk; - entry.populated = true; - entry_added = true; - break; - } - } - - if (!entry_added) { - return BLE_ERROR_NO_MEM; - } - - - // Remove unresolved entries from the resolved list - remove_resolution_entry_from_cache( - [&](resolution_entry_t &entry) { - return entry.identity == nullptr; - } - ); - - // reset pending resolution request - restart_resolution_process(); - - return BLE_ERROR_NO_MEM; + return BLE_ERROR_NOT_IMPLEMENTED; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } ble_error_t PrivateAddressController::remove_device_from_resolving_list( @@ -211,48 +223,58 @@ ble_error_t PrivateAddressController::remove_device_from_resolving_list( const address_t &peer_identity_address ) { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + for (auto &entry : _resolving_list) { + if (entry.populated && + entry.peer_address_type == peer_address_type && + entry.peer_address == peer_identity_address + ) { + remove_resolution_entry_from_cache([&](resolution_entry_t& cache_entry) { + return cache_entry.identity == &entry; + }); + + entry.populated = false; + + restart_resolution_process_on_host(); + } + } + return BLE_ERROR_NONE; +#else if (is_controller_privacy_supported()) { return queue_remove_device_from_resolving_list(peer_address_type, peer_identity_address); } else { - for (auto &entry : _resolving_list) { - if (entry.populated && - entry.peer_address_type == peer_address_type && - entry.peer_address == peer_identity_address - ) { - remove_resolution_entry_from_cache([&](resolution_entry_t& cache_entry) { - return cache_entry.identity == &entry; - }); - - entry.populated = false; - - restart_resolution_process(); - } - } - return BLE_ERROR_NONE; + return BLE_ERROR_NOT_IMPLEMENTED; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } ble_error_t PrivateAddressController::clear_resolving_list() { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + // Remove entry from the resolving list + for (auto &entry : _resolving_list) { + entry.populated = false; + } + // Remove all resolved entries from the cache + remove_resolution_entry_from_cache([&](resolution_entry_t& entry) { + return entry.identity != nullptr; + }); + + restart_resolution_process_on_host(); + + return BLE_ERROR_NONE; +#else if (is_controller_privacy_supported()) { return queue_clear_resolving_list(); } else { - // Remove entry from the resolving list - for (auto &entry : _resolving_list) { - entry.populated = false; - } - // Remove all resolved entries from the cache - remove_resolution_entry_from_cache([&](resolution_entry_t& entry) { - return entry.identity != nullptr; - }); - - restart_resolution_process(); - - return BLE_ERROR_NONE; + return BLE_ERROR_NOT_IMPLEMENTED; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } -bool PrivateAddressController::resolve_address_in_cache( +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + +bool PrivateAddressController::resolve_address_in_host_cache( const address_t &peer_address, target_peer_address_type_t *retrieved_address_type, const address_t **retrieved_address @@ -287,27 +309,24 @@ bool PrivateAddressController::resolve_address_in_cache( return false; } -ble_error_t PrivateAddressController::resolve_address( +ble_error_t PrivateAddressController::resolve_address_on_host( const address_t &peer_address, bool *resolution_complete, target_peer_address_type_t *retrieved_address_type, const address_t **retrieved_address ) { - if (is_controller_privacy_supported()) { - return BLE_ERROR_NOT_IMPLEMENTED; - } - - *resolution_complete = resolve_address_in_cache(peer_address, retrieved_address_type, retrieved_address); + *resolution_complete = resolve_address_in_host_cache(peer_address, retrieved_address_type, retrieved_address); // In the case the address has not been resolved, we start the resolution // process. if (*resolution_complete) { return BLE_ERROR_NONE; } else { - return queue_resolve_address(peer_address); + return queue_resolve_address_on_host(peer_address); } } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void PrivateAddressController::on_resolving_list_action_complete() { @@ -338,6 +357,7 @@ private: PrivacyControlBlock *_next; }; +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION struct PrivateAddressController::PrivacyAddDevToResListControlBlock final : PrivateAddressController::PrivacyControlBlock { PrivacyAddDevToResListControlBlock( @@ -462,10 +482,12 @@ ble_error_t PrivateAddressController::queue_clear_resolving_list() queue_privacy_control_block(cb); return BLE_ERROR_NONE; } +#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION -struct PrivateAddressController::PrivacyResolveAddress final : +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +struct PrivateAddressController::PrivacyResolveAddressOnHost final : PrivateAddressController::PrivacyControlBlock { - PrivacyResolveAddress(const address_t &peer_address) : + PrivacyResolveAddressOnHost(const address_t &peer_address) : PrivacyControlBlock(), peer_address(peer_address) { @@ -508,7 +530,7 @@ private: bool start_next_resolution_round(PrivateAddressController& self) { do { ++resolving_list_index; - if (resolving_list_index == RESOLVING_LIST_SIZE) { + if (resolving_list_index == BLE_SECURITY_DATABASE_MAX_ENTRIES) { notify_completion(self, peer_address,false,nullptr); return true; } @@ -551,9 +573,9 @@ private: bool require_restart = false; }; -ble_error_t PrivateAddressController::queue_resolve_address(const address_t &peer_address) +ble_error_t PrivateAddressController::queue_resolve_address_on_host(const address_t &peer_address) { - auto *cb = new(std::nothrow) PrivacyResolveAddress(peer_address); + auto *cb = new(std::nothrow) PrivacyResolveAddressOnHost(peer_address); if (cb == nullptr) { // Cannot go further return BLE_ERROR_NO_MEM; @@ -566,27 +588,27 @@ ble_error_t PrivateAddressController::queue_resolve_address(const address_t &pee return BLE_ERROR_NONE; } -void PrivateAddressController::restart_resolution_process() +void PrivateAddressController::restart_resolution_process_on_host() { // if processing is active, restart the one running. if (_processing_privacy_control_block && _pending_privacy_control_blocks) { - static_cast(_pending_privacy_control_blocks)->invalidate(); + static_cast(_pending_privacy_control_blocks)->invalidate(); } } void PrivateAddressController::on_private_address_resolved(bool success) { - MBED_ASSERT(is_controller_privacy_supported() == false); if (_pending_privacy_control_blocks == nullptr || _processing_privacy_control_block == false ) { return; } - auto* cb = static_cast(_pending_privacy_control_blocks); + auto* cb = static_cast(_pending_privacy_control_blocks); bool completed = cb->on_resolution_complete(*this, success); process_privacy_control_blocks(completed); } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void PrivateAddressController::clear_privacy_control_blocks() { @@ -649,6 +671,8 @@ void PrivateAddressController::process_privacy_control_blocks(bool cb_completed) _pending_privacy_control_blocks = cb; } +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + template void PrivateAddressController::remove_resolution_entry_from_cache(const Pred &predicate) { @@ -701,4 +725,6 @@ void PrivateAddressController::add_resolution_entry_to_cache( _resolved_list = entry; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + } // namespace ble diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h index 2d7a0f7aad..b7f2c0b44a 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -52,7 +52,7 @@ public: virtual void on_non_resolvable_private_addresses_generated( const address_t &address ) = 0; - +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** * Called when address resolution has been completed by the host. * @@ -73,6 +73,7 @@ public: target_peer_address_type_t identity_address_type, const address_t &identity_address ) = 0; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION }; /** @@ -139,10 +140,12 @@ public: */ bool is_controller_privacy_supported(); +#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** * Enable address resolution by the controller. */ ble_error_t enable_controller_address_resolution(bool enable); +#endif //!BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** * Read the number of entry that can be put in the resolving list. @@ -178,6 +181,7 @@ public: */ ble_error_t clear_resolving_list(); +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** * Resolve a private resolvable address on the host. * @@ -196,13 +200,12 @@ public: * input this will be set to null if the address has not been resolved with * the local irks or a pointer to the identity address if it has been resolved. */ - ble_error_t resolve_address( + ble_error_t resolve_address_on_host( const address_t &peer_address, bool *resolution_complete, target_peer_address_type_t *retrieved_address_type, const address_t **retrieved_address ); - /** * Resolve a private address by looking in the cache. * @@ -215,7 +218,7 @@ public: * * @return True if the address has been found in cache. */ - bool resolve_address_in_cache( + bool resolve_address_in_host_cache( const address_t &peer_address, target_peer_address_type_t *retrieved_address_type, const address_t **retrieved_address @@ -227,7 +230,8 @@ public: * * @param peer_address the address to resolve. */ - ble_error_t queue_resolve_address(const address_t &peer_address); + ble_error_t queue_resolve_address_on_host(const address_t &peer_address); +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION private: @@ -238,7 +242,9 @@ private: // EventHandler implementation void on_resolvable_private_address_generated(const address_t &rpa) final; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void on_private_address_resolved(bool success) final; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void on_resolving_list_action_complete() final; @@ -269,9 +275,11 @@ private: // Queue control block to clear resolving list ble_error_t queue_clear_resolving_list(); - struct PrivacyResolveAddress; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + struct PrivacyResolveAddressOnHost; - void restart_resolution_process(); + void restart_resolution_process_on_host(); +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION // Clear all control blocks void clear_privacy_control_blocks(); @@ -283,12 +291,14 @@ private: // cb_completed is set when the previous block has completed void process_privacy_control_blocks(bool cb_completed); +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + struct resolving_list_entry_t; + template void remove_resolution_entry_from_cache(const Pred& predicate); - struct resolving_list_entry_t; - void add_resolution_entry_to_cache(const address_t& address, resolving_list_entry_t* identity); +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION PalPrivateAddressController &_pal; PalEventQueue &_event_queue; @@ -303,6 +313,7 @@ private: PrivacyControlBlock *_pending_privacy_control_blocks = nullptr; bool _processing_privacy_control_block = false; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION struct resolving_list_entry_t { address_t peer_address = {}; irk_t peer_irk = {}; @@ -310,10 +321,7 @@ private: bool populated = false; }; - // FIXME: Use configuration - static const size_t RESOLVING_LIST_SIZE = 8; - resolving_list_entry_t _resolving_list[RESOLVING_LIST_SIZE]; - + resolving_list_entry_t _resolving_list[BLE_SECURITY_DATABASE_MAX_ENTRIES]; struct resolution_entry_t { address_t address = address_t {}; @@ -321,11 +329,10 @@ private: resolving_list_entry_t *identity = nullptr; }; - // FIXME: Use configuration - static const size_t RESOLVED_ADDRESS_CACHE_SIZE = 16; - resolution_entry_t _resolution_list[RESOLVED_ADDRESS_CACHE_SIZE]; + resolution_entry_t _resolution_list[BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE]; resolution_entry_t *_resolved_list = nullptr; resolution_entry_t *_free_resolution_entries = nullptr; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION }; } diff --git a/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h index 4faa2545e1..657adf9e47 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h @@ -30,11 +30,13 @@ namespace ble { */ struct PalPrivateAddressController { struct EventHandler { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** Called when the address resolution request has completed. * * @param success true if the address has been resolved and false otherwise. */ virtual void on_private_address_resolved(bool success) = 0; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** Called when the resolvable private address request has completed. * From 457268825d23d9fe451d9e3b9bd96c75459243cf Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Mon, 28 Sep 2020 10:35:21 +0100 Subject: [PATCH 47/63] add nrf override for host resolution --- connectivity/FEATURE_BLE/mbed_lib.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/connectivity/FEATURE_BLE/mbed_lib.json b/connectivity/FEATURE_BLE/mbed_lib.json index f7cefee640..75c368dcb6 100644 --- a/connectivity/FEATURE_BLE/mbed_lib.json +++ b/connectivity/FEATURE_BLE/mbed_lib.json @@ -108,5 +108,10 @@ "value": 16, "macro_name": "BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE" } + }, + "target_overrides": { + "MCU_NRF52840": { + "ble-gap-host-based-private-address-resolution": false + } } } From ec2808be31e167ae9fdebb0d86e28c19cc6b207b Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Mon, 28 Sep 2020 15:38:51 +0100 Subject: [PATCH 48/63] filter based on resolving list size --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 17 ++++++++++++----- .../source/generic/PrivateAddressController.cpp | 11 +++++++++++ .../source/generic/PrivateAddressController.h | 9 ++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 6cdbf2414c..74ad53d4bc 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2555,6 +2555,13 @@ void Gap::signal_advertising_report( } } #else + /* filter out unresolved address if at least one bond exists */ + if (_address_registry.read_resolving_list_size() > 0 && + _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && + event.getPeerAddressType() != peer_address_type_t::PUBLIC && + is_random_private_resolvable_address(event.getPeerAddress())) { + return; + } _event_handler->onAdvertisingReport( event ); @@ -2572,15 +2579,15 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( { /* fix the report with the new address if there's an identity found */ if (identity_address) { - /* filter out resolved address based on policy */ - if (_central_privacy_configuration.resolution_strategy == - central_privacy_configuration_t::RESOLVE_AND_FILTER) { - return; - } event.setPeerAddress(*identity_address); event.setPeerAddressType(identity_address_type == target_peer_address_type_t::RANDOM ? peer_address_type_t::RANDOM_STATIC_IDENTITY : peer_address_type_t::PUBLIC_IDENTITY); + } else if (_central_privacy_configuration.resolution_strategy == + central_privacy_configuration_t::RESOLVE_AND_FILTER && + _address_registry.read_resolving_list_size() > 0) { + /* filter out unresolved address if at least one bond exists */ + return; } _event_handler->onAdvertisingReport(event); diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index 31638ad1fb..7934d972e4 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -155,6 +155,11 @@ uint8_t PrivateAddressController::read_resolving_list_capacity() #endif //BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } +uint8_t PrivateAddressController::read_resolving_list_size() +{ + return _resolving_list_size; +} + ble_error_t PrivateAddressController::add_device_to_resolving_list( target_peer_address_type_t peer_address_type, const address_t &peer_identity_address, @@ -185,6 +190,7 @@ ble_error_t PrivateAddressController::add_device_to_resolving_list( entry.peer_irk = peer_irk; entry.populated = true; entry_added = true; + _resolving_list_size++; break; } } @@ -234,6 +240,7 @@ ble_error_t PrivateAddressController::remove_device_from_resolving_list( }); entry.populated = false; + _resolving_list_size--; restart_resolution_process_on_host(); } @@ -259,6 +266,7 @@ ble_error_t PrivateAddressController::clear_resolving_list() remove_resolution_entry_from_cache([&](resolution_entry_t& entry) { return entry.identity != nullptr; }); + _resolving_list_size = 0; restart_resolution_process_on_host(); @@ -380,6 +388,7 @@ struct PrivateAddressController::PrivacyAddDevToResListControlBlock final : _peer_irk, self._local_irk ); + self._resolving_list_size++; return false; } @@ -428,6 +437,7 @@ struct PrivateAddressController::PrivacyRemoveDevFromResListControlBlock final : _peer_identity_address_type, _peer_identity_address ); + self._resolving_list_size--; return false; } @@ -464,6 +474,7 @@ struct PrivateAddressController::PrivacyClearResListControlBlock final : { // Execute command self._pal.clear_resolving_list(); + self._resolving_list_size = 0; return false; } }; diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h index b7f2c0b44a..b1a517ad23 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -148,10 +148,15 @@ public: #endif //!BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION /** - * Read the number of entry that can be put in the resolving list. + * Read the number of entries that can be put in the resolving list. */ uint8_t read_resolving_list_capacity(); + /** + * Read the number of entries that are in the resolving list. + */ + uint8_t read_resolving_list_size(); + /** * Add a new peer to the resolving list. * @param peer_address_type The type of the peer's identity address. @@ -313,6 +318,8 @@ private: PrivacyControlBlock *_pending_privacy_control_blocks = nullptr; bool _processing_privacy_control_block = false; + uint8_t _resolving_list_size = 0; + #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION struct resolving_list_entry_t { address_t peer_address = {}; From b67230cbdb41097344e41d2aa12e6df1664565d5 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Mon, 28 Sep 2020 15:45:53 +0100 Subject: [PATCH 49/63] apply peripheral policy on ll privacy --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 74ad53d4bc..71b2e5247d 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2401,6 +2401,9 @@ void Gap::signal_connection_complete( } } #else + if (!apply_peripheral_privacy_connection_policy(event)) { + return; + } report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); #endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION From d4360383e14c458820fb49d850db6d99bd246c94 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Mon, 28 Sep 2020 16:16:52 +0100 Subject: [PATCH 50/63] do not reject conn if no bond --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 71b2e5247d..734899e693 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2431,6 +2431,10 @@ bool Gap::apply_peripheral_privacy_connection_policy( switch (_peripheral_privacy_configuration.resolution_strategy) { case peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS: + /* if there is no bond then allow unresolved addresses */ + if (_address_registry.read_resolving_list_size() == 0) { + return true; + } _pal_gap.disconnect( connection_handle, local_disconnection_reason_t::AUTHENTICATION_FAILURE From 5216a9aa8ce86bb68b12a7996d0d4748523df250 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Mon, 28 Sep 2020 16:55:17 +0100 Subject: [PATCH 51/63] only apply policy if privacy enabled --- connectivity/FEATURE_BLE/source/generic/GapImpl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 734899e693..ffb42a47e9 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -2401,9 +2401,11 @@ void Gap::signal_connection_complete( } } #else +#if BLE_FEATURE_PRIVACY if (!apply_peripheral_privacy_connection_policy(event)) { return; } +#endif // BLE_FEATURE_PRIVACY report_internal_connection_complete(event); _event_handler->onConnectionComplete(event); #endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION From bb35cba134fb6d9a09c6391e39d1946e61486929 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 29 Sep 2020 10:39:24 +0100 Subject: [PATCH 52/63] BLE: Add function to signal privacy initialization. --- connectivity/FEATURE_BLE/include/ble/Gap.h | 16 ++++++++++ .../FEATURE_BLE/source/generic/GapImpl.cpp | 29 +++++++++++++++++++ .../FEATURE_BLE/source/generic/GapImpl.h | 1 + 3 files changed, 46 insertions(+) diff --git a/connectivity/FEATURE_BLE/include/ble/Gap.h b/connectivity/FEATURE_BLE/include/ble/Gap.h index 88dd9b5824..b056b399b0 100644 --- a/connectivity/FEATURE_BLE/include/ble/Gap.h +++ b/connectivity/FEATURE_BLE/include/ble/Gap.h @@ -538,6 +538,14 @@ public: ) { } + + /** + * Function invoked when the privacy subsystem has been enabled and is + * ready to be used. + */ + virtual void onPrivacyEnabled() + { + } protected: /** * Prevent polymorphic deletion and avoid unnecessary virtual destructor @@ -1244,6 +1252,14 @@ public: * resolved and advertisement packets are forwarded to the application * even if the advertiser private address is unknown. * + * @par Initialization of the privacy subsystem + * + * When privacy is enabled, the system generates new resolvable and non + * resolvable private addresses. Scan, Advertising and Connecting to a peer + * won't be available until the generation process completes. When addresses + * have been generated, the application is notified that privacy + * initialisation as completed with a call to EventHandler::onPrivacyEnabled . + * * @param[in] enable Should be set to true to enable the privacy mode and * false to disable it. * diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index ffb42a47e9..a18d1609b4 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -925,8 +925,20 @@ ble_error_t Gap::enablePrivacy(bool enable) if (_privacy_enabled) { _address_registry.start_private_address_generation(); + if (_address_registry.get_non_resolvable_private_address() != address_t {} && + _address_registry.get_resolvable_private_address() != address_t{} + ) { + _event_queue.post([this] { + if (_event_handler) { + _event_handler->onPrivacyEnabled(); + } + }); + } else { + _privacy_initialization_pending = true; + } } else { _address_registry.stop_private_address_generation(); + _privacy_initialization_pending = false; } #if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -1016,6 +1028,10 @@ ble_error_t Gap::reset() _event_handler = nullptr; +#if BLE_FEATURE_PRIVACY + _privacy_initialization_pending = false; +#endif + #if BLE_ROLE_BROADCASTER _advertising_timeout.detach(); #endif @@ -3174,6 +3190,15 @@ void Gap::on_private_address_generated(bool connectable) return; } + if (_privacy_initialization_pending && + _address_registry.get_resolvable_private_address() != address_t{} && + _address_registry.get_non_resolvable_private_address() != address_t{} + ) { + _privacy_initialization_pending = false; + if (_event_handler) { + _event_handler->onPrivacyEnabled(); + } + } // refresh for address for all connectable advertising sets for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { @@ -3372,6 +3397,10 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ break; } + if (*desired_address == address_t{}) { + return nullptr; + } + if (!address_in_use) { return desired_address; } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index c0ab2a9063..2e841c81e6 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -832,6 +832,7 @@ private: bool _privacy_enabled; #if BLE_FEATURE_PRIVACY + bool _privacy_initialization_pending = false; #if BLE_ROLE_PERIPHERAL peripheral_privacy_configuration_t _peripheral_privacy_configuration; #endif // BLE_ROLE_PERIPHERAL From 4744c87b6cd933fd419a536f503c77f24590d39d Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Wed, 30 Sep 2020 14:01:18 +0100 Subject: [PATCH 53/63] Set privacy mode to device mode in LL. Do not enable address resolution when a new entry is added. --- .../cordio/source/PalPrivateAddressControllerImpl.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp index 1e87e37938..816fddd421 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp @@ -111,9 +111,14 @@ ble_error_t PalPrivateAddressController::add_device_to_resolving_list( peer_identity_address.data(), const_cast(peer_irk.data()), const_cast(local_irk.data()), - true, + false, 0 ); + DmPrivSetPrivacyMode( + peer_address_type.value(), + peer_identity_address.data(), + DM_PRIV_MODE_DEVICE + ); return BLE_ERROR_NONE; } From 18c218b02796673cea6224f5150739cd2a59ae79 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 30 Sep 2020 09:28:34 +0100 Subject: [PATCH 54/63] allow host resolved address to be used for connection --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 152 ++++++++++++++---- .../FEATURE_BLE/source/generic/GapImpl.h | 11 ++ 2 files changed, 136 insertions(+), 27 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index a18d1609b4..247e3c7b28 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -468,7 +468,11 @@ ble_error_t Gap::stopScan() { ble_error_t err; - if ((!_scan_enabled && !_scan_pending) || _scan_pending) { + if ((!_scan_enabled && !_scan_pending) || _scan_pending +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + || _ready_to_connect_to_host_resolved_address +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + ) { return BLE_STACK_BUSY; } @@ -524,6 +528,17 @@ ble_error_t Gap::connect( ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_ready_to_connect_to_host_resolved_address) { + _ready_to_connect_to_host_resolved_address = false; + _connect_to_address_type = peer_address_type_t::ANONYMOUS; + } else if (peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY || + peerAddressType == peer_address_type_t::PUBLIC_IDENTITY) { + _connect_to_address_type = peerAddressType; + _connect_to_address = peerAddress; + } +#endif BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (is_extended_advertising_available() == false) { phy_set_t set(connectionParams.getPhySet()); if (set.count() != 1 || set.get_1m() == false) { @@ -533,35 +548,52 @@ ble_error_t Gap::connect( if (!_scan_enabled) { if (!_active_sets.get(LEGACY_ADVERTISING_HANDLE) && !_pending_sets.get(LEGACY_ADVERTISING_HANDLE) - ) { + ) { _pal_gap.set_random_address(*address); } } else { - // ensure scan is stopped. - _pal_gap.scan_enable(false, false); + stopScan(); + } +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_connect_to_address_type != peer_address_type_t::ANONYMOUS) { + ret = startScan( + (scan_duration_t)connectionParams.getConnectionSupervisionTimeoutArray()[0], + duplicates_filter_t::ENABLE, + (scan_period_t)0 + ); + if (ret == BLE_ERROR_NONE) { + _connection_parameters = new ConnectionParameters(connectionParams); + if (_connection_parameters) { + _ready_to_connect_to_host_resolved_address = true; + } else { + ret = BLE_ERROR_NO_MEM; + } + } + } else +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + { + ret = _pal_gap.create_connection( + connectionParams.getScanIntervalArray()[0], + connectionParams.getScanWindowArray()[0], + connectionParams.getFilter(), + (connection_peer_address_type_t::type) peerAddressType.value(), + peerAddress, + connectionParams.getOwnAddressType(), + connectionParams.getMinConnectionIntervalArray()[0], + connectionParams.getMaxConnectionIntervalArray()[0], + connectionParams.getSlaveLatencyArray()[0], + connectionParams.getConnectionSupervisionTimeoutArray()[0], + connectionParams.getMinEventLengthArray()[0], + connectionParams.getMaxConnectionIntervalArray()[0] + ); } - - ret = _pal_gap.create_connection( - connectionParams.getScanIntervalArray()[0], - connectionParams.getScanWindowArray()[0], - connectionParams.getFilter(), - (connection_peer_address_type_t::type) peerAddressType.value(), - peerAddress, - connectionParams.getOwnAddressType(), - connectionParams.getMinConnectionIntervalArray()[0], - connectionParams.getMaxConnectionIntervalArray()[0], - connectionParams.getSlaveLatencyArray()[0], - connectionParams.getConnectionSupervisionTimeoutArray()[0], - connectionParams.getMinEventLengthArray()[0], - connectionParams.getMaxConnectionIntervalArray()[0] - ); } else { // set the correct mac address before starting scanning. if (!_scan_enabled) { _pal_gap.set_random_address(*address); } else { // ensure scan is stopped. - _pal_gap.extended_scan_enable(false, duplicates_filter_t::DISABLE, 0, 0); + stopScan(); } // reduce the address type to public or random @@ -1150,6 +1182,32 @@ void Gap::on_scan_stopped(bool success) } } +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +void Gap::connecting_to_host_resolved_address_failed() +{ + if (_event_handler) { + _event_handler->onConnectionComplete( + ConnectionCompleteEvent( + BLE_ERROR_NOT_FOUND, + INVALID_ADVERTISING_HANDLE, + connection_role_t::CENTRAL, + peer_address_type_t::ANONYMOUS, + ble::address_t(), + ble::address_t(), + ble::address_t(), + ble::conn_interval_t::max(), + /* dummy slave latency */ 0, + ble::supervision_timeout_t::max(), + /* master clock accuracy */ 0 + ) + ); + } + _ready_to_connect_to_host_resolved_address = false; + _connect_to_address_type = peer_address_type_t::ANONYMOUS; + delete _connection_parameters; + _connection_parameters = nullptr; +} +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::on_scan_timeout() { @@ -1161,6 +1219,13 @@ void Gap::on_scan_timeout() _scan_enabled = false; _scan_pending = false; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_ready_to_connect_to_host_resolved_address) { + connecting_to_host_resolved_address_failed(); + return; + } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); } @@ -1176,6 +1241,13 @@ void Gap::process_legacy_scan_timeout() /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_ready_to_connect_to_host_resolved_address) { + connecting_to_host_resolved_address_failed(); + return; + } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); } @@ -2551,9 +2623,18 @@ void Gap::signal_advertising_report( /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ if (address_resolved) { - _event_handler->onAdvertisingReport( - event - ); + if (_ready_to_connect_to_host_resolved_address) { + if (_connect_to_address_type == event.getDirectAddressType() && + _connect_to_address == event.getDirectAddress()) { + connect(_connect_to_address_type, _connect_to_address, *_connection_parameters); + delete _connection_parameters; + _connection_parameters = nullptr; + } + } else { + _event_handler->onAdvertisingReport( + event + ); + } } else { /* check if there already is a RPA like that in the list of other pending reports */ PendingAdvertisingReportEvent *duplicate_pending_event = _reports_pending_address_resolution.find( @@ -2602,12 +2683,25 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( const address_t *identity_address ) { + + /* fix the report with the new address if there's an identity found */ if (identity_address) { + const peer_address_type_t peer_address_type = (identity_address_type == target_peer_address_type_t::RANDOM) ? + peer_address_type_t::RANDOM_STATIC_IDENTITY + : peer_address_type_t::PUBLIC_IDENTITY; + + if (_ready_to_connect_to_host_resolved_address) { + if (_connect_to_address_type == peer_address_type && _connect_to_address == *identity_address) { + connect(event.getPeerAddressType(), event.getPeerAddress(), *_connection_parameters); + delete _connection_parameters; + _connection_parameters = nullptr; + return; + } + } + event.setPeerAddress(*identity_address); - event.setPeerAddressType(identity_address_type == target_peer_address_type_t::RANDOM ? - peer_address_type_t::RANDOM_STATIC_IDENTITY - : peer_address_type_t::PUBLIC_IDENTITY); + event.setPeerAddressType(peer_address_type); } else if (_central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && _address_registry.read_resolving_list_size() > 0) { @@ -2887,7 +2981,11 @@ ble_error_t Gap::startScan( scan_period_t period ) { - if (_scan_pending || _scan_address_refresh) { + if (_scan_pending || _scan_address_refresh +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + || _ready_to_connect_to_host_resolved_address +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + ) { return BLE_STACK_BUSY; } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 2e841c81e6..2372591290 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -798,6 +798,10 @@ private: const address_t *get_random_address(controller_operation_t operation, size_t advertising_set = 0); +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + void connecting_to_host_resolved_address_failed(); +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + private: /** * Callchain containing all registered callback handlers for shutdown @@ -847,6 +851,13 @@ private: bool _scan_pending = false; bool _scan_interruptible = false; bool _scan_address_refresh = false; +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + bool _ready_to_connect_to_host_resolved_address = false; + peer_address_type_t _connect_to_address_type = peer_address_type_t::ANONYMOUS; + ble::address_t _connect_to_address; + ConnectionParameters *_connection_parameters = nullptr; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + mbed::LowPowerTimeout _advertising_timeout; mbed::LowPowerTimeout _scan_timeout; mbed::LowPowerTicker _address_rotation_ticker; From b0086919ede47a2af6ce16024156e5fdc769a05a Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 30 Sep 2020 11:27:14 +0100 Subject: [PATCH 55/63] scan forever and allow cancellation --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 28 ++++++++----------- .../FEATURE_BLE/source/generic/GapImpl.h | 2 +- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 247e3c7b28..d8cd93accf 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -557,7 +557,7 @@ ble_error_t Gap::connect( #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (_connect_to_address_type != peer_address_type_t::ANONYMOUS) { ret = startScan( - (scan_duration_t)connectionParams.getConnectionSupervisionTimeoutArray()[0], + scan_duration_t::forever(), duplicates_filter_t::ENABLE, (scan_period_t)0 ); @@ -710,6 +710,14 @@ ble_error_t Gap::rejectConnectionParametersUpdate( #if BLE_ROLE_CENTRAL ble_error_t Gap::cancelConnect() { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_ready_to_connect_to_host_resolved_address) { + connecting_to_host_resolved_address_failed(false); + stopScan(); + return BLE_ERROR_NONE; + } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (!_initiating) { return BLE_ERROR_NONE; } @@ -1183,9 +1191,9 @@ void Gap::on_scan_stopped(bool success) } #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION -void Gap::connecting_to_host_resolved_address_failed() +void Gap::connecting_to_host_resolved_address_failed(bool inform_user) { - if (_event_handler) { + if (inform_user && _event_handler) { _event_handler->onConnectionComplete( ConnectionCompleteEvent( BLE_ERROR_NOT_FOUND, @@ -1219,13 +1227,6 @@ void Gap::on_scan_timeout() _scan_enabled = false; _scan_pending = false; -#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_ready_to_connect_to_host_resolved_address) { - connecting_to_host_resolved_address_failed(); - return; - } -#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); } @@ -1241,13 +1242,6 @@ void Gap::process_legacy_scan_timeout() /* legacy scanning timed out is based on timer so we need to stop the scan manually */ _pal_gap.scan_enable(false, false); -#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_ready_to_connect_to_host_resolved_address) { - connecting_to_host_resolved_address_failed(); - return; - } -#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_event_handler) { _event_handler->onScanTimeout(ScanTimeoutEvent()); } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 2372591290..8fa97f28e6 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -799,7 +799,7 @@ private: const address_t *get_random_address(controller_operation_t operation, size_t advertising_set = 0); #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - void connecting_to_host_resolved_address_failed(); + void connecting_to_host_resolved_address_failed(bool inform_user = true); #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION private: From f0bbc4c7ae15996f0aa349cc6f4490e3ad38c53d Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Thu, 1 Oct 2020 10:45:43 +0100 Subject: [PATCH 56/63] use enum for state --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 88 ++++++++++++------- .../FEATURE_BLE/source/generic/GapImpl.h | 13 ++- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index d8cd93accf..45200ef417 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -470,7 +470,7 @@ ble_error_t Gap::stopScan() if ((!_scan_enabled && !_scan_pending) || _scan_pending #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - || _ready_to_connect_to_host_resolved_address + || (_connect_to_host_resolved_address_state != ConnectionToHostResolvedAddressState::idle) #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ) { return BLE_STACK_BUSY; @@ -501,6 +501,12 @@ ble_error_t Gap::connect( const ConnectionParameters &connectionParams ) { +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { + return BLE_ERROR_OPERATION_NOT_PERMITTED; + } +#endif BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + if (!connectionParams.getNumberOfEnabledPhys()) { return BLE_ERROR_INVALID_PARAM; } @@ -529,15 +535,18 @@ ble_error_t Gap::connect( ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_ready_to_connect_to_host_resolved_address) { - _ready_to_connect_to_host_resolved_address = false; - _connect_to_address_type = peer_address_type_t::ANONYMOUS; - } else if (peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY || - peerAddressType == peer_address_type_t::PUBLIC_IDENTITY) { - _connect_to_address_type = peerAddressType; - _connect_to_address = peerAddress; + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::idle) { + if (peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY || + peerAddressType == peer_address_type_t::PUBLIC_IDENTITY) { + _connect_to_host_resolved_address_type = peerAddressType; + _connect_to_host_resolved_address = peerAddress; + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::scan; + } + } else if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::connect) { + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; } -#endif BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (is_extended_advertising_available() == false) { phy_set_t set(connectionParams.getPhySet()); @@ -555,19 +564,20 @@ ble_error_t Gap::connect( stopScan(); } #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_connect_to_address_type != peer_address_type_t::ANONYMOUS) { + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { ret = startScan( scan_duration_t::forever(), duplicates_filter_t::ENABLE, (scan_period_t)0 ); if (ret == BLE_ERROR_NONE) { - _connection_parameters = new ConnectionParameters(connectionParams); - if (_connection_parameters) { - _ready_to_connect_to_host_resolved_address = true; - } else { + _connect_to_host_resolved_address_parameters = new ConnectionParameters(connectionParams); + if (!_connect_to_host_resolved_address_parameters) { + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; ret = BLE_ERROR_NO_MEM; } + } else { + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; } } else #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -711,7 +721,7 @@ ble_error_t Gap::rejectConnectionParametersUpdate( ble_error_t Gap::cancelConnect() { #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_ready_to_connect_to_host_resolved_address) { + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { connecting_to_host_resolved_address_failed(false); stopScan(); return BLE_ERROR_NONE; @@ -1070,7 +1080,12 @@ ble_error_t Gap::reset() #if BLE_FEATURE_PRIVACY _privacy_initialization_pending = false; -#endif +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; + delete _connect_to_host_resolved_address_parameters; + _connect_to_host_resolved_address_parameters = nullptr; +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_FEATURE_PRIVACY #if BLE_ROLE_BROADCASTER _advertising_timeout.detach(); @@ -1210,10 +1225,9 @@ void Gap::connecting_to_host_resolved_address_failed(bool inform_user) ) ); } - _ready_to_connect_to_host_resolved_address = false; - _connect_to_address_type = peer_address_type_t::ANONYMOUS; - delete _connection_parameters; - _connection_parameters = nullptr; + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; + delete _connect_to_host_resolved_address_parameters; + _connect_to_host_resolved_address_parameters = nullptr; } #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -2617,12 +2631,17 @@ void Gap::signal_advertising_report( /* if successful then proceed to call the handler immediately same as for when privacy is disabled */ if (address_resolved) { - if (_ready_to_connect_to_host_resolved_address) { - if (_connect_to_address_type == event.getDirectAddressType() && - _connect_to_address == event.getDirectAddress()) { - connect(_connect_to_address_type, _connect_to_address, *_connection_parameters); - delete _connection_parameters; - _connection_parameters = nullptr; + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { + if (_connect_to_host_resolved_address_type == event.getDirectAddressType() && + _connect_to_host_resolved_address == event.getDirectAddress()) { + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::connect; + connect( + _connect_to_host_resolved_address_type, + _connect_to_host_resolved_address, + *_connect_to_host_resolved_address_parameters + ); + delete _connect_to_host_resolved_address_parameters; + _connect_to_host_resolved_address_parameters = nullptr; } } else { _event_handler->onAdvertisingReport( @@ -2685,11 +2704,16 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( peer_address_type_t::RANDOM_STATIC_IDENTITY : peer_address_type_t::PUBLIC_IDENTITY; - if (_ready_to_connect_to_host_resolved_address) { - if (_connect_to_address_type == peer_address_type && _connect_to_address == *identity_address) { - connect(event.getPeerAddressType(), event.getPeerAddress(), *_connection_parameters); - delete _connection_parameters; - _connection_parameters = nullptr; + if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { + if (_connect_to_host_resolved_address_type == peer_address_type && _connect_to_host_resolved_address == *identity_address) { + _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::connect; + connect( + event.getPeerAddressType(), + event.getPeerAddress(), + *_connect_to_host_resolved_address_parameters + ); + delete _connect_to_host_resolved_address_parameters; + _connect_to_host_resolved_address_parameters = nullptr; return; } } @@ -2977,7 +3001,7 @@ ble_error_t Gap::startScan( { if (_scan_pending || _scan_address_refresh #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - || _ready_to_connect_to_host_resolved_address + || (_connect_to_host_resolved_address_state != ConnectionToHostResolvedAddressState::idle) #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ) { return BLE_STACK_BUSY; diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 8fa97f28e6..61d1c7f28e 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -852,10 +852,15 @@ private: bool _scan_interruptible = false; bool _scan_address_refresh = false; #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - bool _ready_to_connect_to_host_resolved_address = false; - peer_address_type_t _connect_to_address_type = peer_address_type_t::ANONYMOUS; - ble::address_t _connect_to_address; - ConnectionParameters *_connection_parameters = nullptr; + enum class ConnectionToHostResolvedAddressState : uint8_t { + idle, + scan, + connect + }; + ble::address_t _connect_to_host_resolved_address; + peer_address_type_t _connect_to_host_resolved_address_type = peer_address_type_t::ANONYMOUS; + ConnectionToHostResolvedAddressState _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; + ConnectionParameters *_connect_to_host_resolved_address_parameters = nullptr; #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION mbed::LowPowerTimeout _advertising_timeout; From 6ee5740941bc26f8d117c49b133778c49fbdaaf5 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Thu, 1 Oct 2020 11:16:44 +0100 Subject: [PATCH 57/63] use _initiating to block scan manipulation --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 45200ef417..548fcaa0ac 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -468,11 +468,7 @@ ble_error_t Gap::stopScan() { ble_error_t err; - if ((!_scan_enabled && !_scan_pending) || _scan_pending -#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - || (_connect_to_host_resolved_address_state != ConnectionToHostResolvedAddressState::idle) -#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - ) { + if ((!_scan_enabled && !_scan_pending) || _scan_pending || _initiating) { return BLE_STACK_BUSY; } @@ -535,15 +531,26 @@ ble_error_t Gap::connect( ble_error_t ret = BLE_ERROR_INTERNAL_STACK_FAILURE; #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + /* if host resolution is used we need to connect in two passes, first we scan for addresses to find + * a resolving match and then we call connect again with the correct address */ if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::idle) { if (peerAddressType == peer_address_type_t::RANDOM_STATIC_IDENTITY || peerAddressType == peer_address_type_t::PUBLIC_IDENTITY) { + + _connect_to_host_resolved_address_parameters = new ConnectionParameters(connectionParams); + if (!_connect_to_host_resolved_address_parameters) { + return BLE_ERROR_NO_MEM; + } + _connect_to_host_resolved_address_type = peerAddressType; _connect_to_host_resolved_address = peerAddress; _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::scan; } } else if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::connect) { + /* the first pass of connect has completed and this is the second connect that doesn't require + * address resolution */ _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; + _initiating = false; } #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -570,13 +577,7 @@ ble_error_t Gap::connect( duplicates_filter_t::ENABLE, (scan_period_t)0 ); - if (ret == BLE_ERROR_NONE) { - _connect_to_host_resolved_address_parameters = new ConnectionParameters(connectionParams); - if (!_connect_to_host_resolved_address_parameters) { - _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; - ret = BLE_ERROR_NO_MEM; - } - } else { + if (ret != BLE_ERROR_NONE) { _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; } } else @@ -1077,7 +1078,7 @@ ble_error_t Gap::reset() shutdownCallChain.clear(); _event_handler = nullptr; - + _initiating = false; #if BLE_FEATURE_PRIVACY _privacy_initialization_pending = false; #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -1228,6 +1229,7 @@ void Gap::connecting_to_host_resolved_address_failed(bool inform_user) _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle; delete _connect_to_host_resolved_address_parameters; _connect_to_host_resolved_address_parameters = nullptr; + _initiating = false; } #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -2999,11 +3001,7 @@ ble_error_t Gap::startScan( scan_period_t period ) { - if (_scan_pending || _scan_address_refresh -#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - || (_connect_to_host_resolved_address_state != ConnectionToHostResolvedAddressState::idle) -#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - ) { + if (_scan_pending || _scan_address_refresh || _initiating) { return BLE_STACK_BUSY; } From f32141a05137301eadb8b8143063bd6220d9d679 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Fri, 2 Oct 2020 17:20:21 +0100 Subject: [PATCH 58/63] BLE: Notify application when advertising start or stop Applicable for legacy and extended advertising. --- connectivity/FEATURE_BLE/include/ble/Gap.h | 12 ++++ .../FEATURE_BLE/include/ble/gap/Events.h | 59 ++++++++++++++++++- .../FEATURE_BLE/source/generic/GapImpl.cpp | 21 ++++++- .../FEATURE_BLE/source/generic/GapImpl.h | 1 + 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/Gap.h b/connectivity/FEATURE_BLE/include/ble/Gap.h index b056b399b0..9965e220dd 100644 --- a/connectivity/FEATURE_BLE/include/ble/Gap.h +++ b/connectivity/FEATURE_BLE/include/ble/Gap.h @@ -314,6 +314,17 @@ public: { } + /** + * Called when advertising starts. + * + * @param event Advertising start event. + * + * @see startAdvertising() + */ + virtual void onAdvertisingStart(const AdvertisingStartEvent &event) + { + } + /** * Called when advertising ends. * @@ -732,6 +743,7 @@ public: * @param maxEvents Max number of events produced during advertising - 0 means no limit. * @return BLE_ERROR_NONE on success. * + * @see EventHandler::onAdvertisingStart when the advertising starts. * @see EventHandler::onScanRequestReceived when a scan request is received. * @see EventHandler::onAdvertisingEnd when the advertising ends. * @see EventHandler::onConnectionComplete when the device gets connected diff --git a/connectivity/FEATURE_BLE/include/ble/gap/Events.h b/connectivity/FEATURE_BLE/include/ble/gap/Events.h index 022b6035c1..a181f7b762 100644 --- a/connectivity/FEATURE_BLE/include/ble/gap/Events.h +++ b/connectivity/FEATURE_BLE/include/ble/gap/Events.h @@ -575,15 +575,47 @@ private: */ struct ScanTimeoutEvent { }; +/** + * Event produced when advertising start. + * + * @see ble::Gap::EventHandler::onAdvertisingStart(). + */ +struct AdvertisingStartEvent { +#if !defined(DOXYGEN_ONLY) + + /** Create an advertising start event. + * + * @param advHandle Advertising set handle. + */ + AdvertisingStartEvent(advertising_handle_t advHandle) : + advHandle(advHandle) + { + } + +#endif + + /** Get advertising handle. */ + advertising_handle_t getAdvHandle() const + { + return advHandle; + } + +private: + advertising_handle_t advHandle; +}; + /** * Event produced when advertising ends. * * @see ble::Gap::EventHandler::onAdvertisingEnd(). + * + * @note The connection handle, connected flag and completed_event fields are + * valid if the flag legacy is not set to true. */ struct AdvertisingEndEvent { #if !defined(DOXYGEN_ONLY) - /** Create advertising end event. + /** Create an extended advertising end event. * * @param advHandle Advertising set handle. * @param connection Connection handle. @@ -599,7 +631,19 @@ struct AdvertisingEndEvent { advHandle(advHandle), connection(connection), completed_events(completed_events), - connected(connected) + connected(connected), + legacy(false) + { + } + + /** Create a legacy advertising end event. + */ + AdvertisingEndEvent() : + advHandle(LEGACY_ADVERTISING_HANDLE), + connection(), + completed_events(0), + connected(false), + legacy(true) { } @@ -629,11 +673,22 @@ struct AdvertisingEndEvent { return connected; } + /** Is the end of legacy advertising. + * + * If it is the return of getConnection() getCompleted_events() and isConnected() + * must be discarded + */ + bool isLegacy() const + { + return legacy; + } + private: advertising_handle_t advHandle; connection_handle_t connection; uint8_t completed_events; bool connected; + bool legacy; }; /** diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 548fcaa0ac..04a857424c 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -1199,6 +1199,7 @@ void Gap::on_scan_stopped(bool success) if (restart_advertising) { _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); startAdvertising(LEGACY_ADVERTISING_HANDLE); + _adv_started_from_refresh.set(LEGACY_ADVERTISING_HANDLE); } _scan_address_refresh = false; @@ -2804,11 +2805,18 @@ void Gap::on_legacy_advertising_started() { _active_sets.set(LEGACY_ADVERTISING_HANDLE); _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); + + if (_adv_started_from_refresh.get(LEGACY_ADVERTISING_HANDLE)) { + _adv_started_from_refresh.clear(LEGACY_ADVERTISING_HANDLE); + } else if(_event_handler) { + _event_handler->onAdvertisingStart( + AdvertisingStartEvent(LEGACY_ADVERTISING_HANDLE) + ); + } } void Gap::on_legacy_advertising_stopped() { - _active_sets.clear(LEGACY_ADVERTISING_HANDLE); _pending_sets.clear(LEGACY_ADVERTISING_HANDLE); @@ -2819,10 +2827,13 @@ void Gap::on_legacy_advertising_stopped() if (_address_refresh_sets.get(LEGACY_ADVERTISING_HANDLE) && !wait_for_scan_stop) { _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); startAdvertising(LEGACY_ADVERTISING_HANDLE); + _adv_started_from_refresh.set(LEGACY_ADVERTISING_HANDLE); if (restart_scan) { _scan_address_refresh = false; startScan(); } + } else if (_event_handler) { + _event_handler->onAdvertisingEnd(AdvertisingEndEvent()); } } @@ -2831,6 +2842,13 @@ void Gap::on_advertising_set_started(const mbed::Span& handles) for (const auto &handle : handles) { _active_sets.set(handle); _pending_sets.clear(handle); + if (_adv_started_from_refresh.get(handle)) { + _adv_started_from_refresh.clear(handle); + } else if (_event_handler) { + _event_handler->onAdvertisingStart( + AdvertisingStartEvent(LEGACY_ADVERTISING_HANDLE) + ); + } } } @@ -2848,6 +2866,7 @@ void Gap::on_advertising_set_terminated( if (_address_refresh_sets.get(advertising_handle) && !connection_handle) { _address_refresh_sets.clear(advertising_handle); startAdvertising(advertising_handle); + _adv_started_from_refresh.set(advertising_handle); return; } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 61d1c7f28e..27c04826a2 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -923,6 +923,7 @@ private: BitArray _pending_sets; BitArray _address_refresh_sets; BitArray _interruptible_sets; + BitArray _adv_started_from_refresh; bool _user_manage_connection_parameter_requests : 1; From e1842ccd8797e569c32a90d6e6b794dbd8186c30 Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 13 Oct 2020 16:16:17 +0100 Subject: [PATCH 59/63] BLE: Workaround for WB55 connection event The connection event reported by the WB55 is incorrect if controller privacy is not enable and the peer connects with an unknown private resolvable address: The RPA field contains the connection address (it should be empty) and the peer address is all FF while it should be equal to the connection address. --- .../source/cordio/source/PalGapImpl.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h index 9b4e99fbbc..3ea3fd41e8 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h @@ -364,18 +364,30 @@ private: static GapConnectionCompleteEvent convert(const hciLeConnCmplEvt_t *conn_evt) { + const bdAddr_t *peer_rpa = &conn_evt->peerRpa; + const bdAddr_t *peer_address = &conn_evt->peerAddr; + +#if defined(TARGET_MCU_STM32WB55xx) + const bdAddr_t invalidAddress = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + if (conn_evt->addrType == DM_ADDR_RANDOM && + memcmp(peer_address, invalidAddress, sizeof(invalidAddress)) == 0 && + memcmp(peer_rpa, invalidAddress, sizeof(invalidAddress) != 0) + ) { + std::swap(peer_rpa, peer_address); + } +#endif return GapConnectionCompleteEvent( conn_evt->status, // note the usage of the stack handle, not the HCI handle conn_evt->hdr.param, (connection_role_t::type) conn_evt->role, (peer_address_type_t::type) conn_evt->addrType, - conn_evt->peerAddr, + *peer_address, conn_evt->connInterval, conn_evt->connLatency, conn_evt->supTimeout, conn_evt->localRpa, - conn_evt->peerRpa + *peer_rpa ); } }; From 2a4a097a9358c911bff62d07d4ff817a0b0af73c Mon Sep 17 00:00:00 2001 From: Vincent Coubard Date: Tue, 13 Oct 2020 16:16:48 +0100 Subject: [PATCH 60/63] BLE: Take advantage of controller based address resolution on WB55 --- connectivity/FEATURE_BLE/mbed_lib.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connectivity/FEATURE_BLE/mbed_lib.json b/connectivity/FEATURE_BLE/mbed_lib.json index 75c368dcb6..ad105f5b66 100644 --- a/connectivity/FEATURE_BLE/mbed_lib.json +++ b/connectivity/FEATURE_BLE/mbed_lib.json @@ -112,6 +112,9 @@ "target_overrides": { "MCU_NRF52840": { "ble-gap-host-based-private-address-resolution": false + }, + "NUCLEO_WB55RG": { + "ble-gap-host-based-private-address-resolution": false } } } From 3f9798b52df47e4239befa49e93ca6b943fb2bf2 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Tue, 13 Oct 2020 16:21:29 +0100 Subject: [PATCH 61/63] Fix conditional compilation based on config --- .../FEATURE_BLE/include/ble/SecurityManager.h | 2 + .../FEATURE_BLE/source/SecurityManager.cpp | 4 +- .../cordio/source/BLEInstanceBaseImpl.cpp | 23 +- .../source/cordio/source/PalGapImpl.cpp | 21 +- .../source/cordio/source/PalGapImpl.h | 2 + .../PalPrivateAddressControllerImpl.cpp | 3 + .../source/PalPrivateAddressControllerImpl.h | 6 +- .../cordio/source/PalSecurityManagerImpl.cpp | 4 + .../FEATURE_BLE/source/generic/GapImpl.cpp | 214 ++++++++++-------- .../FEATURE_BLE/source/generic/GapImpl.h | 64 +++++- .../generic/PrivateAddressController.cpp | 4 + .../source/generic/PrivateAddressController.h | 4 + .../source/generic/SecurityManagerImpl.cpp | 21 +- .../source/generic/SecurityManagerImpl.h | 18 +- connectivity/FEATURE_BLE/source/pal/PalGap.h | 22 ++ .../source/pal/PalPrivateAddressController.h | 3 + 16 files changed, 282 insertions(+), 133 deletions(-) diff --git a/connectivity/FEATURE_BLE/include/ble/SecurityManager.h b/connectivity/FEATURE_BLE/include/ble/SecurityManager.h index 4f6bb67cc9..b3bc6e582f 100644 --- a/connectivity/FEATURE_BLE/include/ble/SecurityManager.h +++ b/connectivity/FEATURE_BLE/include/ble/SecurityManager.h @@ -835,6 +835,7 @@ public: // Privacy // +#if BLE_FEATURE_PRIVACY /** * Sets how often the address is rotated when privacy is enabled. * @@ -845,6 +846,7 @@ public: ble_error_t setPrivateAddressTimeout( uint16_t timeout_in_seconds ); +#endif // BLE_FEATURE_PRIVACY /* Event callback handlers. */ public: diff --git a/connectivity/FEATURE_BLE/source/SecurityManager.cpp b/connectivity/FEATURE_BLE/source/SecurityManager.cpp index 71c16c86e4..3cebbb713f 100644 --- a/connectivity/FEATURE_BLE/source/SecurityManager.cpp +++ b/connectivity/FEATURE_BLE/source/SecurityManager.cpp @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -192,12 +192,14 @@ ble_error_t SecurityManager::getSigningKey(ble::connection_handle_t connectionHa return impl->getSigningKey(connectionHandle, authenticated); } +#if BLE_FEATURE_PRIVACY ble_error_t SecurityManager::setPrivateAddressTimeout( uint16_t timeout_in_seconds ) { return impl->setPrivateAddressTimeout(timeout_in_seconds); } +#endif // BLE_FEATURE_PRIVACY void SecurityManager::onShutdown(const SecurityManagerShutdownCallback_t& callback) { diff --git a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp index e32fbeeb4d..f7aa9bb750 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/BLEInstanceBaseImpl.cpp @@ -200,9 +200,10 @@ ble::impl::Gap &BLEInstanceBase::getGapImpl() static ble::impl::Gap gap( _event_queue, ble::impl::PalGap::get_gap(), - cordio_gap_service, - ble::impl::PalSecurityManager::get_security_manager(), - getPrivateAddressRegistry() + cordio_gap_service +#if BLE_FEATURE_PRIVACY + , getPrivateAddressRegistry() +#endif // BLE_FEATURE_PRIVACY ); return gap; } @@ -221,7 +222,6 @@ const ble::Gap &BLEInstanceBase::getGap() const }; #if BLE_FEATURE_GATT_SERVER - ble::impl::GattServer &BLEInstanceBase::getGattServerImpl() { return ble::impl::GattServer::getInstance(); @@ -239,11 +239,9 @@ const ble::GattServer &BLEInstanceBase::getGattServer() const auto &self = const_cast(*this); return const_cast(self.getGattServer()); } - #endif // BLE_FEATURE_GATT_SERVER #if BLE_FEATURE_GATT_CLIENT - ble::impl::GattClient &BLEInstanceBase::getGattClientImpl() { static ble::impl::GattClient gatt_client(getPalGattClient()); @@ -262,11 +260,9 @@ PalGattClient &BLEInstanceBase::getPalGattClient() static PalAttClientToGattClient pal_gatt_client(impl::PalAttClient::get_client()); return pal_gatt_client; } - #endif // BLE_FEATURE_GATT_CLIENT #if BLE_FEATURE_SECURITY - ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl() { // Creation of a proxy monitor to let the security manager register to @@ -286,13 +282,16 @@ ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl() static ble::impl::SecurityManager m_instance( ble::impl::PalSecurityManager::get_security_manager(), getGapImpl(), - signing_event_monitor, - getPrivateAddressRegistry() + signing_event_monitor +#if BLE_FEATURE_PRIVACY + , getPrivateAddressRegistry() +#endif //BLE_FEATURE_PRIVACY ); return m_instance; } +#if BLE_FEATURE_SECURITY ble::SecurityManager &BLEInstanceBase::getSecurityManager() { static ble::SecurityManager m_instance(&getSecurityManagerImpl()); @@ -304,6 +303,7 @@ const ble::SecurityManager &BLEInstanceBase::getSecurityManager() const const BLEInstanceBase &self = const_cast(*this); return const_cast(self.getSecurityManager()); } +#endif // BLE_FEATURE_SECURITY #if BLE_FEATURE_PRIVACY ble::PrivateAddressController &BLEInstanceBase::getPrivateAddressRegistry() @@ -315,8 +315,7 @@ ble::PrivateAddressController &BLEInstanceBase::getPrivateAddressRegistry() ); return registry; } -#endif - +#endif // BLE_FEATURE_PRIVACY #endif // BLE_FEATURE_SECURITY void BLEInstanceBase::waitForEvent() diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp index 80bdea8ae1..0c6b963012 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.cpp @@ -16,6 +16,7 @@ * limitations under the License. */ #include "source/PalGapImpl.h" +#include "ble/common/BLERoles.h" #include "hci_api.h" #include "dm_api.h" #include "dm_main.h" @@ -571,7 +572,9 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) } break; #endif // BLE_FEATURE_PHY_MANAGEMENT + #if BLE_FEATURE_PERIODIC_ADVERTISING +#if BLE_ROLE_OBSERVER case DM_PER_ADV_SYNC_EST_IND: { if (!handler) { break; @@ -619,8 +622,10 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) handler->on_periodic_advertising_sync_loss(evt->syncHandle); } break; +#endif // BLE_ROLE_OBSERVER #endif // BLE_FEATURE_PERIODIC_ADVERTISING +#if BLE_ROLE_BROADCASTER case DM_ADV_START_IND: if (!handler) { break; @@ -634,6 +639,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) } handler->on_legacy_advertising_stopped(); break; +#endif // BLE_ROLE_BROADCASTER #if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER case DM_SCAN_REQ_RCVD_IND: { @@ -743,7 +749,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) #endif // BLE_FEATURE_EXTENDED_ADVERTISING #endif // BLE_ROLE_OBSERVER -#if BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL +#if BLE_FEATURE_CONNECTABLE case DM_REM_CONN_PARAM_REQ_IND: { if (!handler) { break; @@ -769,7 +775,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) get_gap().get_running_conn_direct_adv_cb(evt->hdr.param); if (adv_cb) { adv_cb->state = direct_adv_cb_t::free; - +#if BLE_ROLE_BROADCASTER if (handler) { handler->on_advertising_set_terminated( hci_error_code_t(evt->status), @@ -778,6 +784,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) 0 ); } +#endif // BLE_ROLE_BROADCASTER } } } @@ -794,7 +801,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) } } break; -#endif // BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL +#endif // BLE_FEATURE_CONNECTABLE } // all handlers are stored in a static array @@ -802,12 +809,12 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg) #if BLE_ROLE_OBSERVER &event_handler, #endif // BLE_ROLE_OBSERVER -#if BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL +#if BLE_FEATURE_CONNECTABLE &event_handler, &event_handler, &event_handler, &event_handler, -#endif // BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL +#endif // BLE_FEATURE_CONNECTABLE &dummy_gap_event_handler }; @@ -846,7 +853,7 @@ ble_error_t PalGap::set_advertising_set_random_address( return BLE_ERROR_NONE; } - +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t PalGap::set_extended_advertising_parameters( advertising_handle_t advertising_handle, advertising_event_properties_t event_properties, @@ -986,7 +993,7 @@ ble_error_t PalGap::set_extended_advertising_parameters( peer_address_type ); } - +#endif // BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t PalGap::set_periodic_advertising_parameters( advertising_handle_t advertising_handle, diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h index 9b4e99fbbc..7a46f15ddc 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalGapImpl.h @@ -174,6 +174,7 @@ public: const address_t &address ) final; +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t set_extended_advertising_parameters( advertising_handle_t advertising_handle, advertising_event_properties_t event_properties, @@ -191,6 +192,7 @@ public: uint8_t advertising_sid, bool scan_request_notification ) final; +#endif // BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t set_periodic_advertising_parameters( advertising_handle_t advertising_handle, diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp index 816fddd421..fda0aedebe 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.cpp @@ -15,6 +15,8 @@ * limitations under the License. */ +#if BLE_FEATURE_PRIVACY + #include "PalPrivateAddressControllerImpl.h" #include "dm_api.h" @@ -232,3 +234,4 @@ bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg) } // namespace impl } // namespace ble +#endif // BLE_FEATURE_PRIVACY diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h index 6076f8cbee..564303bee1 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalPrivateAddressControllerImpl.h @@ -1,7 +1,7 @@ /* mbed Microcontroller Library * Copyright (c) 2020 ARM Limited * SPDX-License-Identifier: Apache-2.0 - * + * * 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 @@ -18,6 +18,8 @@ #ifndef BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H #define BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H +#if BLE_FEATURE_PRIVACY + #include "source/pal/PalPrivateAddressController.h" #include "dm_api.h" @@ -91,4 +93,6 @@ private: } // namespace impl } // namespace ble +#endif // BLE_FEATURE_PRIVACY + #endif //BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H diff --git a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp index 42c8b668fe..ee76884a1a 100644 --- a/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/cordio/source/PalSecurityManagerImpl.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#if BLE_FEATURE_SECURITY + #include #include "ble/common/BLERoles.h" @@ -789,3 +791,5 @@ PalSecurityManagerEventHandler *PalSecurityManager::get_event_handler() } // namespace impl } // namespace ble + +#endif // BLE_FEATURE_SECURITY diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 04a857424c..79dff45e97 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -76,6 +76,7 @@ static bool is_in_range(T value, T lower_bound, T higher_bound) return true; } +#if BLE_FEATURE_CONNECTABLE /* * Return true of the connection parameters are acceptable as preferred connection * parameters. @@ -128,6 +129,7 @@ bool is_preferred_connection_params_valid(const Gap::PreferredConnectionParams_t return true; } +#endif // BLE_FEATURE_CONNECTABLE /** * Check if random bytes of an address are valid. @@ -231,6 +233,7 @@ bool is_random_address(const address_t &address) is_random_static_address(address); } +#if BLE_FEATURE_WHITELIST /* * Return true if the whitelist in input is valid or false otherwise. */ @@ -294,7 +297,9 @@ whitelist_address_type_t to_whitelist_address_type( whitelist_address_type_t::PUBLIC_DEVICE_ADDRESS : whitelist_address_type_t::RANDOM_DEVICE_ADDRESS; } +#endif // BLE_FEATURE_WHITELIST +#if BLE_FEATURE_CONNECTABLE microsecond_t minSupervisionTimeout( const conn_interval_t &maxConnectionInterval, const slave_latency_t &slaveLatency @@ -304,6 +309,7 @@ microsecond_t minSupervisionTimeout( // Section 7.8.12 LE Create Connection return (1 + slaveLatency.value()) * maxConnectionInterval * 2; } +#endif // BLE_FEATURE_CONNECTABLE bool is_connectable_advertising(const AdvertisingParameters ¶ms) { @@ -313,36 +319,49 @@ bool is_connectable_advertising(const AdvertisingParameters ¶ms) } // end of anonymous namespace +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_BROADCASTER const peripheral_privacy_configuration_t Gap::default_peripheral_privacy_configuration = { /* use_non_resolvable_random_address */ false, /* resolution_strategy */ peripheral_privacy_configuration_t::PERFORM_PAIRING_PROCEDURE }; +#endif // BLE_ROLE_BROADCASTER - +#if BLE_ROLE_OBSERVER const central_privacy_configuration_t Gap::default_central_privacy_configuration = { /* use_non_resolvable_random_address */ false, /* resolution_strategy */ central_privacy_configuration_t::RESOLVE_AND_FORWARD }; +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY Gap::Gap( ble::PalEventQueue &event_queue, ble::PalGap &pal_gap, - ble::PalGenericAccessService &generic_access_service, - ble::PalSecurityManager &pal_sm, - ble::PrivateAddressController &pal_addr_reg + ble::PalGenericAccessService &generic_access_service +#if BLE_FEATURE_PRIVACY + , ble::PrivateAddressController &pal_addr_reg +#endif //BLE_FEATURE_PRIVACY ) : _event_queue(event_queue), _pal_gap(pal_gap), _gap_service(generic_access_service), - _pal_sm(pal_sm), +#if BLE_FEATURE_PRIVACY _address_registry(pal_addr_reg), +#endif // BLE_FEATURE_PRIVACY _address_type(own_address_type_t::PUBLIC), _initiator_policy_mode(initiator_policy_t::NO_FILTER), _scanning_filter_policy(scanning_filter_policy_t::NO_FILTER), _advertising_filter_policy(advertising_filter_policy_t::NO_FILTER), _whitelist(), _privacy_enabled(false), +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_BROADCASTER _peripheral_privacy_configuration(default_peripheral_privacy_configuration), +#endif // BLE_ROLE_BROADCASTER +#if BLE_ROLE_OBSERVER _central_privacy_configuration(default_central_privacy_configuration), +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY _scan_enabled(false), _advertising_timeout(), _scan_timeout(), @@ -358,7 +377,9 @@ Gap::Gap( _random_static_identity_address = _pal_gap.get_random_address(); _pal_gap.set_event_handler(this); +#if BLE_FEATURE_PRIVACY _address_registry.set_event_handler(this); +#endif // BLE_FEATURE_PRIVACY } @@ -501,7 +522,7 @@ ble_error_t Gap::connect( if (_connect_to_host_resolved_address_state == ConnectionToHostResolvedAddressState::scan) { return BLE_ERROR_OPERATION_NOT_PERMITTED; } -#endif BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION if (!connectionParams.getNumberOfEnabledPhys()) { return BLE_ERROR_INVALID_PARAM; @@ -674,10 +695,7 @@ ble_error_t Gap::updateConnectionParameters( maxConnectionEventLength.value() ); } -#endif - -#if BLE_FEATURE_CONNECTABLE ble_error_t Gap::acceptConnectionParametersUpdate( connection_handle_t connectionHandle, conn_interval_t minConnectionInterval, @@ -702,10 +720,7 @@ ble_error_t Gap::acceptConnectionParametersUpdate( maxConnectionEventLength.value() ); } -#endif - -#if BLE_FEATURE_CONNECTABLE ble_error_t Gap::rejectConnectionParametersUpdate( connection_handle_t connectionHandle ) @@ -715,8 +730,7 @@ ble_error_t Gap::rejectConnectionParametersUpdate( hci_error_code_t::UNACCEPTABLE_CONNECTION_PARAMETERS ); } -#endif - +#endif // BLE_FEATURE_CONNECTABLE #if BLE_ROLE_CENTRAL ble_error_t Gap::cancelConnect() @@ -739,17 +753,14 @@ ble_error_t Gap::cancelConnect() } return ret; } -#endif +#endif // BLE_ROLE_CENTRAL #if BLE_FEATURE_PHY_MANAGEMENT ble_error_t Gap::readPhy(ble::connection_handle_t connection) { return _pal_gap.read_phy(connection); } -#endif - -#if BLE_FEATURE_PHY_MANAGEMENT ble_error_t Gap::setPreferredPhys( const phy_set_t *txPhys, const phy_set_t *rxPhys @@ -759,10 +770,7 @@ ble_error_t Gap::setPreferredPhys( phy_set_t rx_phys(rxPhys ? rxPhys->value() : 0); return _pal_gap.set_preferred_phys(tx_phys, rx_phys); } -#endif - -#if BLE_FEATURE_PHY_MANAGEMENT ble_error_t Gap::setPhy( ble::connection_handle_t connection, const phy_set_t *txPhys, @@ -774,8 +782,6 @@ ble_error_t Gap::setPhy( phy_set_t rx_phys(rxPhys ? rxPhys->value() : 0); return _pal_gap.set_phy(connection, tx_phys, rx_phys, codedSymbol); } -#endif - void Gap::on_read_phy( hci_error_code_t hci_status, @@ -793,7 +799,7 @@ void Gap::on_read_phy( _event_handler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); } } - +#endif // BLE_FEATURE_PHY_MANAGEMENT void Gap::on_data_length_change( connection_handle_t connection_handle, @@ -806,7 +812,7 @@ void Gap::on_data_length_change( } } - +#if BLE_FEATURE_PHY_MANAGEMENT void Gap::on_phy_update_complete( hci_error_code_t hci_status, ble::connection_handle_t connection_handle, @@ -823,7 +829,7 @@ void Gap::on_phy_update_complete( _event_handler->onPhyUpdateComplete(status, connection_handle, tx_phy, rx_phy); } } - +#endif // BLE_FEATURE_PHY_MANAGEMENT #if BLE_FEATURE_CONNECTABLE ble_error_t Gap::disconnect( @@ -833,18 +839,14 @@ ble_error_t Gap::disconnect( { return _pal_gap.disconnect(connectionHandle, reason); } -#endif - +#endif // BLE_FEATURE_CONNECTABLE #if BLE_FEATURE_WHITELIST uint8_t Gap::getMaxWhitelistSize(void) const { return _pal_gap.read_white_list_capacity(); } -#endif - -#if BLE_FEATURE_WHITELIST ble_error_t Gap::getWhitelist(whitelist_t &whitelist) const { if (initialize_whitelist() == false) { @@ -862,10 +864,7 @@ ble_error_t Gap::getWhitelist(whitelist_t &whitelist) const whitelist.capacity = _whitelist.capacity; return BLE_ERROR_NONE; } -#endif - -#if BLE_FEATURE_WHITELIST ble_error_t Gap::setWhitelist(const whitelist_t &whitelist) { if (is_whitelist_valid(whitelist) == false) { @@ -957,8 +956,7 @@ ble_error_t Gap::setWhitelist(const whitelist_t &whitelist) return BLE_ERROR_NONE; } -#endif - +#endif // BLE_FEATURE_WHITELIST #if BLE_FEATURE_PRIVACY ble_error_t Gap::enablePrivacy(bool enable) @@ -1000,7 +998,7 @@ ble_error_t Gap::enablePrivacy(bool enable) return BLE_ERROR_NONE; } -#endif +#endif // BLE_FEATURE_PRIVACY #if BLE_FEATURE_PRIVACY @@ -1019,12 +1017,7 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( return BLE_ERROR_NONE; } -#endif -#endif - -#if BLE_FEATURE_PRIVACY -#if BLE_ROLE_BROADCASTER ble_error_t Gap::getPeripheralPrivacyConfiguration( peripheral_privacy_configuration_t *configuration ) @@ -1033,9 +1026,8 @@ ble_error_t Gap::getPeripheralPrivacyConfiguration( return BLE_ERROR_NONE; } -#endif -#endif - +#endif // BLE_ROLE_BROADCASTER +#endif // BLE_FEATURE_PRIVACY #if BLE_FEATURE_PRIVACY #if BLE_ROLE_OBSERVER @@ -1053,12 +1045,7 @@ ble_error_t Gap::setCentralPrivacyConfiguration( return BLE_ERROR_NONE; } -#endif -#endif - -#if BLE_FEATURE_PRIVACY -#if BLE_ROLE_OBSERVER ble_error_t Gap::getCentralPrivacyConfiguration( central_privacy_configuration_t *configuration ) @@ -1067,9 +1054,8 @@ ble_error_t Gap::getCentralPrivacyConfiguration( return BLE_ERROR_NONE; } -#endif -#endif - +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY ble_error_t Gap::reset() { @@ -1159,6 +1145,7 @@ Gap::GapShutdownCallbackChain_t &Gap::onShutdown() return shutdownCallChain; } +#if BLE_ROLE_OBSERVER void Gap::on_scan_started(bool success) { _scan_pending = false; @@ -1193,19 +1180,22 @@ void Gap::on_scan_stopped(bool success) wait_for_advertising_stop = false; restart_advertising = false; } -#endif +#endif // BLE_FEATURE_EXTENDED_ADVERTISING if (_scan_address_refresh && !wait_for_advertising_stop) { +#if BLE_ROLE_BROADCASTER if (restart_advertising) { _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); startAdvertising(LEGACY_ADVERTISING_HANDLE); _adv_started_from_refresh.set(LEGACY_ADVERTISING_HANDLE); } +#endif // BLE_ROLE_BROADCASTER _scan_address_refresh = false; startScan(); } } +#endif // BLE_ROLE_OBSERVER #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::connecting_to_host_resolved_address_failed(bool inform_user) @@ -1234,6 +1224,7 @@ void Gap::connecting_to_host_resolved_address_failed(bool inform_user) } #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#if BLE_ROLE_OBSERVER void Gap::on_scan_timeout() { if (!_scan_enabled) { @@ -1248,8 +1239,9 @@ void Gap::on_scan_timeout() _event_handler->onScanTimeout(ScanTimeoutEvent()); } } +#endif // BLE_ROLE_OBSERVER - +#if BLE_ROLE_OBSERVER void Gap::process_legacy_scan_timeout() { if (!_scan_enabled) { @@ -1263,14 +1255,14 @@ void Gap::process_legacy_scan_timeout() _event_handler->onScanTimeout(ScanTimeoutEvent()); } } +#endif // BLE_ROLE_OBSERVER - +#if BLE_ROLE_BROADCASTER void Gap::on_advertising_timeout() { _event_queue.post(mbed::callback(this, &Gap::process_advertising_timeout)); } - void Gap::process_advertising_timeout() { if (!_active_sets.get(LEGACY_ADVERTISING_HANDLE)) { @@ -1279,7 +1271,7 @@ void Gap::process_advertising_timeout() stopAdvertising(LEGACY_ADVERTISING_HANDLE); } - +#endif // BLE_ROLE_BROADCASTER void Gap::on_gap_event_received(const GapEvent &e) { @@ -1315,7 +1307,7 @@ void Gap::on_gap_event_received(const GapEvent &e) } } - +#if BLE_ROLE_OBSERVER void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) { for (size_t i = 0; i < e.size(); ++i) { @@ -1373,8 +1365,9 @@ void Gap::on_advertising_report(const GapAdvertisingReportEvent &e) ); } } +#endif // BLE_ROLE_OBSERVER - +#if BLE_FEATURE_CONNECTABLE void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) { if (e.role == connection_role_t::CENTRAL) { @@ -1435,7 +1428,6 @@ void Gap::on_connection_complete(const GapConnectionCompleteEvent &e) } } - void Gap::on_disconnection_complete(const GapDisconnectionCompleteEvent &e) { if (e.status == hci_error_code_t::SUCCESS) { @@ -1461,7 +1453,6 @@ void Gap::on_disconnection_complete(const GapDisconnectionCompleteEvent &e) } } - void Gap::on_connection_parameter_request(const GapRemoteConnectionParameterRequestEvent &e) { if (_user_manage_connection_parameter_requests) { @@ -1491,7 +1482,6 @@ void Gap::on_connection_parameter_request(const GapRemoteConnectionParameterRequ } } - void Gap::on_connection_update(const GapConnectionUpdateEvent &e) { if (!_event_handler) { @@ -1508,7 +1498,7 @@ void Gap::on_connection_update(const GapConnectionUpdateEvent &e) ) ); } - +#endif //BLE_FEATURE_CONNECTABLE void Gap::on_unexpected_error(const GapUnexpectedErrorEvent &e) { @@ -1516,7 +1506,6 @@ void Gap::on_unexpected_error(const GapUnexpectedErrorEvent &e) // has been updated. } - own_address_type_t Gap::get_own_address_type(AddressUseType_t address_use_type) { #if BLE_FEATURE_PRIVACY @@ -1555,7 +1544,7 @@ own_address_type_t Gap::get_own_address_type(AddressUseType_t address_use_type) } } - +#if BLE_FEATURE_WHITELIST bool Gap::initialize_whitelist() const { if (_whitelist.addresses != nullptr) { @@ -1578,6 +1567,7 @@ bool Gap::initialize_whitelist() const return true; } +#endif // BLE_FEATURE_WHITELIST #if BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t Gap::update_ll_address_resolution_setting() @@ -1792,6 +1782,8 @@ ble_error_t Gap::setAdvertisingParameters( } #endif +#if BLE_ROLE_BROADCASTER +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t Gap::setExtendedAdvertisingParameters( advertising_handle_t handle, const AdvertisingParameters ¶ms @@ -1841,7 +1833,8 @@ ble_error_t Gap::setExtendedAdvertisingParameters( return err; } - +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_BROADCASTER #if BLE_ROLE_BROADCASTER ble_error_t Gap::setAdvertisingPayload( @@ -1874,7 +1867,7 @@ ble_error_t Gap::setAdvertisingScanResponse( } #endif - +#if BLE_ROLE_BROADCASTER ble_error_t Gap::setAdvertisingData( advertising_handle_t handle, Span payload, @@ -1998,7 +1991,7 @@ ble_error_t Gap::setAdvertisingData( return BLE_ERROR_NONE; #endif // BLE_FEATURE_EXTENDED_ADVERTISING } - +#endif // BLE_ROLE_BROADCASTER #if BLE_ROLE_BROADCASTER ble_error_t Gap::startAdvertising( @@ -2028,12 +2021,14 @@ ble_error_t Gap::startAdvertising( MBED_WARNING(MBED_ERROR_INVALID_SIZE, "Payload size exceeds size allowed for connectable advertising."); return BLE_ERROR_INVALID_STATE; } +#endif // BLE_FEATURE_EXTENDED_ADVERTISING const address_t* random_address = get_random_address(controller_operation_t::advertising, handle); if (!random_address) { return BLE_ERROR_INVALID_STATE; } +#if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { // Addresses can be updated if the set is not advertising if (!_active_sets.get(handle)) { @@ -2345,9 +2340,11 @@ bool Gap::isPeriodicAdvertisingActive(advertising_handle_t handle) return _active_periodic_sets.get(handle); } -#endif -#endif +#endif // BLE_FEATURE_PERIODIC_ADVERTISING +#endif // BLE_ROLE_BROADCASTER +#if BLE_ROLE_OBSERVER +#if BLE_FEATURE_EXTENDED_ADVERTISING void Gap::on_extended_advertising_report( advertising_event_t event_type, const connection_peer_address_type_t *address_type, @@ -2390,6 +2387,8 @@ void Gap::on_extended_advertising_report( event ); } +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif //BLE_ROLE_OBSERVER #if BLE_FEATURE_CONNECTABLE void Gap::report_internal_connection_complete(const ConnectionCompleteEvent& event) @@ -2600,7 +2599,8 @@ void Gap::signal_advertising_report( AdvertisingReportEvent& event ) { -#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#if BLE_FEATURE_PRIVACY +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION bool address_resolved = false; /* if address resolution is not needed or already handled then the address is already resolved */ @@ -2684,10 +2684,11 @@ void Gap::signal_advertising_report( is_random_private_resolvable_address(event.getPeerAddress())) { return; } +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_FEATURE_PRIVACY _event_handler->onAdvertisingReport( event ); -#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } #endif //BLE_ROLE_OBSERVER @@ -2699,8 +2700,6 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( const address_t *identity_address ) { - - /* fix the report with the new address if there's an identity found */ if (identity_address) { const peer_address_type_t peer_address_type = (identity_address_type == target_peer_address_type_t::RANDOM) ? @@ -2735,6 +2734,8 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( #endif // BLE_ROLE_OBSERVER #endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#if BLE_ROLE_OBSERVER +#if BLE_FEATURE_PERIODIC_ADVERTISING void Gap::on_periodic_advertising_sync_established( hci_error_code_t error, sync_handle_t sync_handle, @@ -2800,7 +2801,10 @@ void Gap::on_periodic_advertising_sync_loss(sync_handle_t sync_handle) PeriodicAdvertisingSyncLoss(sync_handle) ); } +#endif // BLE_FEATURE_PERIODIC_ADVERTISING +#endif // BLE_ROLE_OBSERVER +#if BLE_ROLE_BROADCASTER void Gap::on_legacy_advertising_started() { _active_sets.set(LEGACY_ADVERTISING_HANDLE); @@ -2828,10 +2832,12 @@ void Gap::on_legacy_advertising_stopped() _address_refresh_sets.clear(LEGACY_ADVERTISING_HANDLE); startAdvertising(LEGACY_ADVERTISING_HANDLE); _adv_started_from_refresh.set(LEGACY_ADVERTISING_HANDLE); +#if BLE_ROLE_OBSERVER if (restart_scan) { _scan_address_refresh = false; startScan(); } +#endif // BLE_ROLE_OBSERVER } else if (_event_handler) { _event_handler->onAdvertisingEnd(AdvertisingEndEvent()); } @@ -2884,7 +2890,6 @@ void Gap::on_advertising_set_terminated( ); } - void Gap::on_scan_request_received( advertising_handle_t advertising_handle, connection_peer_address_type_t scanner_address_type, @@ -2903,8 +2908,9 @@ void Gap::on_scan_request_received( ) ); } +#endif // BLE_ROLE_BROADCASTER - +#if BLE_FEATURE_CONNECTABLE void Gap::on_connection_update_complete( hci_error_code_t status, connection_handle_t connection_handle, @@ -2928,7 +2934,6 @@ void Gap::on_connection_update_complete( ); } - void Gap::on_remote_connection_parameter( connection_handle_t connection_handle, uint16_t connection_interval_min, @@ -2960,7 +2965,7 @@ void Gap::on_remote_connection_parameter( ); } } - +#endif // BLE_FEATURE_CONNECTABLE #if BLE_ROLE_OBSERVER ble_error_t Gap::setScanParameters(const ScanParameters ¶ms) @@ -3283,6 +3288,8 @@ bool Gap::is_extended_advertising_available() #endif // BLE_FEATURE_EXTENDED_ADVERTISING } +#if BLE_ROLE_BROADCASTER +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t Gap::prepare_legacy_advertising_set(const AdvertisingParameters& parameters) { if (_existing_sets.get(LEGACY_ADVERTISING_HANDLE)) { @@ -3300,13 +3307,15 @@ ble_error_t Gap::prepare_legacy_advertising_set(const AdvertisingParameters& par return err; } +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_BROADCASTER void Gap::setEventHandler(Gap::EventHandler *handler) { _event_handler = handler; } - +#if BLE_FEATURE_PRIVACY void Gap::on_resolvable_private_addresses_generated(const address_t &address) { on_private_address_generated(true); @@ -3333,6 +3342,7 @@ void Gap::on_private_address_generated(bool connectable) } } +#if BLE_ROLE_BROADCASTER // refresh for address for all connectable advertising sets for (size_t i = 0; i < BLE_GAP_MAX_ADVERTISING_SETS; ++i) { if (!_pending_sets.get(i) && _active_sets.get(i) && @@ -3345,7 +3355,9 @@ void Gap::on_private_address_generated(bool connectable) _address_refresh_sets.set(i); } } +#endif // BLE_ROLE_BROADCASTER +#if BLE_ROLE_OBSERVER // refresh scanning address if (_scan_enabled && !_scan_pending && _scan_interruptible && !_central_privacy_configuration.use_non_resolvable_random_address == connectable @@ -3356,9 +3368,9 @@ void Gap::on_private_address_generated(bool connectable) } _scan_address_refresh = true; } +#endif // BLE_ROLE_OBSERVER } -#if BLE_FEATURE_PRIVACY #if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void Gap::on_address_resolution_completed( const address_t &peer_resolvable_address, @@ -3452,26 +3464,36 @@ void Gap::update_advertising_set_connectable_attribute( } } -// Note a call to this functions implies that the const address_t *Gap::get_random_address(controller_operation_t operation, size_t set_id) { - const auto &resolvable_address = _address_registry.get_resolvable_private_address(); - const auto &non_resolvable_address = _address_registry.get_non_resolvable_private_address(); - bool central_non_resolvable = _central_privacy_configuration.use_non_resolvable_random_address; - bool peripheral_non_resolvable = _peripheral_privacy_configuration.use_non_resolvable_random_address; - - const address_t *address_in_use = nullptr; - const address_t *desired_address = nullptr; - - // If privacy is not enabled, then the random address is always the random - // static address. - if (_privacy_enabled == false) { + // If privacy is not enabled, then the random address is always the random static address. +#if BLE_FEATURE_PRIVACY + if (_privacy_enabled == false) +#endif // BLE_FEATURE_PRIVACY + { return &_random_static_identity_address; } +#if BLE_FEATURE_PRIVACY + const auto &resolvable_address = _address_registry.get_resolvable_private_address(); + const auto &non_resolvable_address = _address_registry.get_non_resolvable_private_address(); + +#if BLE_ROLE_OBSERVER + bool central_non_resolvable = _central_privacy_configuration.use_non_resolvable_random_address; +#else + bool central_non_resolvable = false; +#endif // BLE_ROLE_OBSERVER +#if BLE_ROLE_BROADCASTER + bool peripheral_non_resolvable = _peripheral_privacy_configuration.use_non_resolvable_random_address; +#else + bool peripheral_non_resolvable = false; +#endif // BLE_ROLE_BROADCASTER + const address_t *address_in_use = nullptr; + const address_t *desired_address = nullptr; + bool advertising_use_main_address = true; - // Extended advertising is a special case as the address isn't shared with - // the main address. + + // Extended advertising is a special case as each set has its own address #if !CORDIO_GLOBAL_RANDOM_ADDRESS_FOR_CONNECTION #if BLE_FEATURE_EXTENDED_ADVERTISING if (is_extended_advertising_available()) { @@ -3488,7 +3510,6 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ #endif #endif - // For other cases we first compute the address being used and then compares // it to the address to use to determine if the address is correct or not. if (_initiating) { @@ -3544,6 +3565,7 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ } return desired_address; +#endif // BLE_FEATURE_PRIVACY } diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 27c04826a2..dc0d5cec57 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -59,10 +59,15 @@ class BLEInstanceBase; class Gap : public ble::PalConnectionMonitor, - public PalGapEventHandler, - public PrivateAddressController::EventHandler { + public PalGapEventHandler +#if BLE_FEATURE_PRIVACY + , public PrivateAddressController::EventHandler +#endif //BLE_FEATURE_PRIVACY + { friend PalConnectionMonitor; +#if BLE_FEATURE_PRIVACY friend PalGapEventHandler; +#endif //BLE_FEATURE_PRIVACY friend PalGap; friend impl::BLEInstanceBase; @@ -72,17 +77,23 @@ class Gap : public: using PreferredConnectionParams_t = ::ble::Gap::PreferredConnectionParams_t ; +#if BLE_FEATURE_PRIVACY +#if BLE_ROLE_BROADCASTER /** * Default peripheral privacy configuration. */ static const peripheral_privacy_configuration_t default_peripheral_privacy_configuration; +#endif // BLE_ROLE_BROADCASTER +#if BLE_ROLE_OBSERVER /** * Default peripheral privacy configuration. */ static const central_privacy_configuration_t default_central_privacy_configuration; +#endif // BLE_ROLE_OBSERVER +#endif // BLE_FEATURE_PRIVACY public: void setEventHandler(EventHandler *handler); @@ -542,13 +553,15 @@ private: Gap( ble::PalEventQueue &event_queue, ble::PalGap &pal_gap, - ble::PalGenericAccessService &generic_access_service, - ble::PalSecurityManager &pal_sm, - ble::PrivateAddressController &pal_addr_reg + ble::PalGenericAccessService &generic_access_service +#if BLE_FEATURE_PRIVACY + , ble::PrivateAddressController &pal_addr_reg +#endif // BLE_FEATURE_PRIVACY ); ~Gap(); +#if BLE_ROLE_BROADCASTER ble_error_t setAdvertisingData( advertising_handle_t handle, Span payload, @@ -559,11 +572,15 @@ private: void on_advertising_timeout(); void process_advertising_timeout(); +#endif // BLE_ROLE_BROADCASTER void on_gap_event_received(const GapEvent &e); +#if BLE_ROLE_OBSERVER void on_advertising_report(const GapAdvertisingReportEvent &e); +#endif // BLE_ROLE_OBSERVER +#if BLE_FEATURE_CONNECTABLE void on_connection_complete(const GapConnectionCompleteEvent &e); void on_disconnection_complete(const GapDisconnectionCompleteEvent &e); @@ -573,6 +590,7 @@ private: ); void on_connection_update(const GapConnectionUpdateEvent &e); +#endif // BLE_FEATURE_CONNECTABLE void on_unexpected_error(const GapUnexpectedErrorEvent &e); @@ -585,20 +603,30 @@ private: own_address_type_t get_own_address_type(AddressUseType_t address_use_type); +#if BLE_FEATURE_WHITELIST bool initialize_whitelist() const; +#endif // BLE_FEATURE_WHITELIST #if BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION ble_error_t update_ll_address_resolution_setting(); #endif // BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#if BLE_ROLE_BROADCASTER +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t setExtendedAdvertisingParameters( advertising_handle_t handle, const AdvertisingParameters ¶meters ); +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_BROADCASTER bool is_extended_advertising_available(); +#if BLE_ROLE_BROADCASTER +#if BLE_FEATURE_EXTENDED_ADVERTISING ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters); +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_BROADCASTER #if BLE_FEATURE_CONNECTABLE /** Call the internal handlers that report to the security manager and GATT @@ -665,12 +693,14 @@ private: /* implements PalGap::EventHandler */ private: +#if BLE_FEATURE_PHY_MANAGEMENT void on_read_phy( hci_error_code_t hci_status, connection_handle_t connection_handle, phy_t tx_phy, phy_t rx_phy ) override; +#endif // BLE_FEATURE_PHY_MANAGEMENT void on_data_length_change( connection_handle_t connection_handle, @@ -678,13 +708,17 @@ private: uint16_t rx_size ) override; +#if BLE_FEATURE_PHY_MANAGEMENT void on_phy_update_complete( hci_error_code_t hci_status, connection_handle_t connection_handle, phy_t tx_phy, phy_t rx_phy ) override; +#endif // BLE_FEATURE_PHY_MANAGEMENT +#if BLE_ROLE_OBSERVER +#if BLE_FEATURE_EXTENDED_ADVERTISING void on_extended_advertising_report( advertising_event_t event_type, const connection_peer_address_type_t *address_type, @@ -700,7 +734,9 @@ private: uint8_t data_length, const uint8_t *data ) override; +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#if BLE_FEATURE_PERIODIC_ADVERTISING void on_periodic_advertising_sync_established( hci_error_code_t error, sync_handle_t sync_handle, @@ -722,7 +758,10 @@ private: ) override; void on_periodic_advertising_sync_loss(sync_handle_t sync_handle) override; +#endif // BLE_FEATURE_PERIODIC_ADVERTISING +#endif // BLE_ROLE_OBSERVER +#if BLE_ROLE_BROADCASTER void on_legacy_advertising_started() override; void on_legacy_advertising_stopped() override; @@ -741,7 +780,9 @@ private: connection_peer_address_type_t scanner_address_type, const ble::address_t &address ) override; +#endif // BLE_ROLE_BROADCASTER +#if BLE_FEATURE_CONNECTABLE void on_connection_update_complete( hci_error_code_t status, connection_handle_t connection_handle, @@ -757,7 +798,9 @@ private: uint16_t connection_latency, uint16_t supervision_timeout ) override; +#endif // BLE_FEATURE_CONNECTABLE +#if BLE_ROLE_OBSERVER void on_scan_started(bool success) override; void on_scan_stopped(bool success) override; @@ -765,7 +808,9 @@ private: void on_scan_timeout() override; void process_legacy_scan_timeout(); +#endif // BLE_ROLE_OBSERVER +#if BLE_FEATURE_PRIVACY /* Implement PrivateAddressController::EventHandler */ private: void on_resolvable_private_addresses_generated(const address_t &address) final; @@ -773,14 +818,16 @@ private: void on_non_resolvable_private_addresses_generated(const address_t &address) final; void on_private_address_generated(bool connectable); -#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION + +#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION void on_address_resolution_completed( const address_t &peer_resolvable_address, bool resolved, target_peer_address_type_t identity_address_type, const address_t &identity_address ) final; -#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION +#endif // BLE_FEATURE_PRIVACY private: bool is_advertising() const; @@ -826,8 +873,9 @@ private: PalEventQueue &_event_queue; PalGap &_pal_gap; PalGenericAccessService &_gap_service; - PalSecurityManager &_pal_sm; +#if BLE_FEATURE_PRIVACY PrivateAddressController &_address_registry; +#endif // BLE_FEATURE_PRIVACY ble::own_address_type_t _address_type; initiator_policy_t _initiator_policy_mode; scanning_filter_policy_t _scanning_filter_policy; diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp index 7934d972e4..f1f9c70e5a 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.cpp @@ -15,6 +15,8 @@ * limitations under the License. */ +#if BLE_FEATURE_PRIVACY + #include "PrivateAddressController.h" namespace ble { @@ -739,3 +741,5 @@ void PrivateAddressController::add_resolution_entry_to_cache( #endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION } // namespace ble + +#endif // BLE_FEATURE_PRIVACY diff --git a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h index b1a517ad23..e24de9d6c4 100644 --- a/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/generic/PrivateAddressController.h @@ -18,6 +18,8 @@ #ifndef BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H #define BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H +#if BLE_FEATURE_PRIVACY + #include #include "drivers/LowPowerTicker.h" @@ -344,4 +346,6 @@ private: } +#endif // BLE_FEATURE_PRIVACY + #endif //BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp index 02db71a9ad..a057f60e55 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.cpp @@ -16,6 +16,8 @@ * limitations under the License. */ +#if BLE_FEATURE_SECURITY + #include "ble/BLE.h" #include "ble/common/BLERoles.h" @@ -136,7 +138,7 @@ ble_error_t SecurityManager::init( // set the local identity address and irk if (result == BLE_ERROR_NONE) { result = init_identity(); - } + } #endif // BLE_FEATURE_PRIVACY if (result != BLE_ERROR_NONE) { @@ -739,7 +741,7 @@ ble_error_t SecurityManager::getSigningKey(connection_handle_t connection, bool // Privacy // - +#if BLE_FEATURE_PRIVACY ble_error_t SecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; @@ -748,6 +750,7 @@ ble_error_t SecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_second ); return BLE_ERROR_NONE; } +#endif // BLE_FEATURE_PRIVACY //////////////////////////////////////////////////////////////////////////// // Authentication @@ -980,7 +983,7 @@ ble_error_t SecurityManager::init_database( return BLE_ERROR_NONE; } - +#if BLE_FEATURE_PRIVACY ble_error_t SecurityManager::init_resolving_list() { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; @@ -1006,8 +1009,9 @@ ble_error_t SecurityManager::init_resolving_list() return BLE_ERROR_NONE; } +#endif // BLE_FEATURE_PRIVACY - +#if BLE_FEATURE_SIGNING ble_error_t SecurityManager::init_signing() { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; @@ -1028,8 +1032,9 @@ ble_error_t SecurityManager::init_signing() return _pal.set_csrk(*pcsrk, local_sign_counter); } +#endif // BLE_FEATURE_SIGNING - +#if BLE_FEATURE_PRIVACY ble_error_t SecurityManager::init_identity() { if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE; @@ -1076,7 +1081,7 @@ ble_error_t SecurityManager::init_identity() } return err; } - +#endif // BLE_FEATURE_PRIVACY ble_error_t SecurityManager::get_random_data(uint8_t *buffer, size_t size) { @@ -1383,6 +1388,7 @@ void SecurityManager::on_identity_list_retrieved( { typedef advertising_peer_address_type_t address_type_t; +#if BLE_FEATURE_PRIVACY _private_address_controller.clear_resolving_list(); for (size_t i = 0; i < count; ++i) { _private_address_controller.add_device_to_resolving_list( @@ -1393,6 +1399,7 @@ void SecurityManager::on_identity_list_retrieved( identity_list[i].irk ); } +#endif // BLE_FEATURE_PRIVACY delete [] identity_list.data(); } @@ -2080,3 +2087,5 @@ void SecurityManager::setSecurityManagerEventHandler(EventHandler* handler) } /* namespace impl */ } /* namespace ble */ + +#endif // BLE_FEATURE_SECURITY diff --git a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h index 576fd6ae92..a969b36dd9 100644 --- a/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/SecurityManagerImpl.h @@ -185,9 +185,11 @@ public: // Privacy // +#if BLE_FEATURE_PRIVACY ble_error_t setPrivateAddressTimeout( uint16_t timeout_in_seconds ); +#endif // BLE_FEATURE_PRIVACY /* Event callback handlers. */ public: @@ -451,14 +453,18 @@ public: SecurityManager( ble::PalSecurityManager &palImpl, ble::PalConnectionMonitor &connMonitorImpl, - ble::PalSigningMonitor &signingMonitorImpl, - PrivateAddressController &privateAddressController + ble::PalSigningMonitor &signingMonitorImpl +#if BLE_FEATURE_PRIVACY + , PrivateAddressController &privateAddressController +#endif // BLE_FEATURE_PRIVACY ) : eventHandler(nullptr), _pal(palImpl), _connection_monitor(connMonitorImpl), _signing_monitor(signingMonitorImpl), _db(nullptr), +#if BLE_FEATURE_PRIVACY _private_address_controller(privateAddressController), +#endif // BLE_FEATURE_PRIVACY _default_authentication(0), _default_key_distribution(KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), @@ -493,11 +499,17 @@ private: ble_error_t init_database(const char *db_path = nullptr); +#if BLE_FEATURE_PRIVACY ble_error_t init_resolving_list(); +#endif // BLE_FEATURE_PRIVACY +#if BLE_FEATURE_SIGNING ble_error_t init_signing(); +#endif // BLE_FEATURE_SIGNING +#if BLE_FEATURE_PRIVACY ble_error_t init_identity(); +#endif // BLE_FEATURE_PRIVACY ble_error_t get_random_data( uint8_t *buffer, @@ -641,7 +653,9 @@ private: PalSigningMonitor &_signing_monitor; SecurityDb *_db; +#if BLE_FEATURE_PRIVACY PrivateAddressController &_private_address_controller; +#endif // BLE_FEATURE_PRIVACY /* OOB data */ address_t _oob_local_address; diff --git a/connectivity/FEATURE_BLE/source/pal/PalGap.h b/connectivity/FEATURE_BLE/source/pal/PalGap.h index ca538de892..e0caee3050 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalGap.h +++ b/connectivity/FEATURE_BLE/source/pal/PalGap.h @@ -21,6 +21,7 @@ #include "platform/Callback.h" +#include "ble/common/BLERoles.h" #include "source/pal/GapTypes.h" #include "source/pal/GapEvents.h" #include "ble/common/blecommon.h" @@ -29,6 +30,8 @@ namespace ble { struct PalGapEventHandler { public: + +#if BLE_FEATURE_PHY_MANAGEMENT /** * @copydoc PalGap::EventHandler::onReadPhy */ @@ -38,6 +41,7 @@ public: ble::phy_t tx_phy, ble::phy_t rx_phy ) = 0; +#endif // BLE_FEATURE_PHY_MANAGEMENT /** * @copydoc PalGap::EventHandler::onDataLengthChange @@ -48,6 +52,7 @@ public: uint16_t rx_size ) = 0; +#if BLE_FEATURE_PHY_MANAGEMENT /** * @copydoc PalGap::EventHandler::onPhyUpdateComplete */ @@ -57,7 +62,10 @@ public: ble::phy_t tx_phy, ble::phy_t rx_phy ) = 0; +#endif // BLE_FEATURE_PHY_MANAGEMENT +#if BLE_FEATURE_EXTENDED_ADVERTISING +#if BLE_ROLE_OBSERVER /** Called on advertising report event. * * @param event_type Type of advertising used. @@ -92,7 +100,11 @@ public: uint8_t data_length, const uint8_t *data_size ) = 0; +#endif // BLE_FEATURE_EXTENDED_ADVERTISING +#endif // BLE_ROLE_OBSERVER +#if BLE_FEATURE_PERIODIC_ADVERTISING +#if BLE_ROLE_OBSERVER /** Called on advertising sync event. * * @param error SUCCESS if synchronisation was achieved. @@ -140,7 +152,10 @@ public: virtual void on_periodic_advertising_sync_loss( sync_handle_t sync_handle ) = 0; +#endif // BLE_FEATURE_PERIODIC_ADVERTISING +#endif // BLE_ROLE_OBSERVER +#if BLE_ROLE_OBSERVER /** * Called when scanning start */ @@ -155,7 +170,9 @@ public: /** Called when scanning times out. */ virtual void on_scan_timeout( ) = 0; +#endif // BLE_ROLE_OBSERVER +#if BLE_ROLE_BROADCASTER /** * Called when legacy advertising has been effectively started. */ @@ -196,7 +213,9 @@ public: connection_peer_address_type_t scanner_address_type, const address_t &address ) = 0; +#endif // BLE_ROLE_BROADCASTER +#if BLE_FEATURE_CONNECTABLE virtual void on_connection_update_complete( hci_error_code_t status, connection_handle_t connection_handle, @@ -212,6 +231,7 @@ public: uint16_t connection_latency, uint16_t supervision_timeout ) = 0; +#endif // BLE_FEATURE_CONNECTABLE }; /** @@ -375,6 +395,7 @@ public: advertising_filter_policy_t advertising_filter_policy ) = 0; +#if BLE_FEATURE_EXTENDED_ADVERTISING /** * Define the advertising parameters of an advertising set. * @@ -451,6 +472,7 @@ public: uint8_t advertising_sid, bool scan_request_notification ) = 0; +#endif // BLE_FEATURE_EXTENDED_ADVERTISING /** * Configure periodic advertising parameters of an advertising set. diff --git a/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h index 657adf9e47..0f286181d5 100644 --- a/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h +++ b/connectivity/FEATURE_BLE/source/pal/PalPrivateAddressController.h @@ -18,6 +18,8 @@ #ifndef BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H #define BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H +#if BLE_FEATURE_PRIVACY + #include "ble/common/BLETypes.h" #include "ble/common/blecommon.h" #include "GapTypes.h" @@ -244,5 +246,6 @@ struct PalPrivateAddressController { } // namespace ble +#endif // BLE_FEATURE_PRIVACY #endif //BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H From 9f09bb49560c5adf3f5b9772dfd51beb4610b8dc Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Tue, 13 Oct 2020 17:40:37 +0100 Subject: [PATCH 62/63] rename private address controller to match security manager --- .../FEATURE_BLE/source/generic/GapImpl.cpp | 46 +++++++++---------- .../FEATURE_BLE/source/generic/GapImpl.h | 4 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp index 79dff45e97..3fc2c045df 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.cpp @@ -340,13 +340,13 @@ Gap::Gap( ble::PalGap &pal_gap, ble::PalGenericAccessService &generic_access_service #if BLE_FEATURE_PRIVACY - , ble::PrivateAddressController &pal_addr_reg + , ble::PrivateAddressController &private_address_controller #endif //BLE_FEATURE_PRIVACY ) : _event_queue(event_queue), _pal_gap(pal_gap), _gap_service(generic_access_service), #if BLE_FEATURE_PRIVACY - _address_registry(pal_addr_reg), + _private_address_controller(private_address_controller), #endif // BLE_FEATURE_PRIVACY _address_type(own_address_type_t::PUBLIC), _initiator_policy_mode(initiator_policy_t::NO_FILTER), @@ -378,7 +378,7 @@ Gap::Gap( _pal_gap.set_event_handler(this); #if BLE_FEATURE_PRIVACY - _address_registry.set_event_handler(this); + _private_address_controller.set_event_handler(this); #endif // BLE_FEATURE_PRIVACY } @@ -973,9 +973,9 @@ ble_error_t Gap::enablePrivacy(bool enable) _privacy_enabled = enable; if (_privacy_enabled) { - _address_registry.start_private_address_generation(); - if (_address_registry.get_non_resolvable_private_address() != address_t {} && - _address_registry.get_resolvable_private_address() != address_t{} + _private_address_controller.start_private_address_generation(); + if (_private_address_controller.get_non_resolvable_private_address() != address_t {} && + _private_address_controller.get_resolvable_private_address() != address_t{} ) { _event_queue.post([this] { if (_event_handler) { @@ -986,12 +986,12 @@ ble_error_t Gap::enablePrivacy(bool enable) _privacy_initialization_pending = true; } } else { - _address_registry.stop_private_address_generation(); + _private_address_controller.stop_private_address_generation(); _privacy_initialization_pending = false; } #if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_address_registry.is_controller_privacy_supported()) { + if (_private_address_controller.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } #endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -1010,7 +1010,7 @@ ble_error_t Gap::setPeripheralPrivacyConfiguration( _peripheral_privacy_configuration = *configuration; #if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_address_registry.is_controller_privacy_supported()) { + if (_private_address_controller.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } #endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -1038,7 +1038,7 @@ ble_error_t Gap::setCentralPrivacyConfiguration( _central_privacy_configuration = *configuration; #if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION - if (_address_registry.is_controller_privacy_supported()) { + if (_private_address_controller.is_controller_privacy_supported()) { update_ll_address_resolution_setting(); } #endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -1589,7 +1589,7 @@ ble_error_t Gap::update_ll_address_resolution_setting() #endif // BLE_ROLE_OBSERVER } - return _address_registry.enable_controller_address_resolution(enable); + return _private_address_controller.enable_controller_address_resolution(enable); } #endif // BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION @@ -2451,7 +2451,7 @@ void Gap::signal_connection_complete( /* first try to resolve synchronously in cache */ if (!address_resolved) { - address_resolved = _address_registry.resolve_address_in_host_cache( + address_resolved = _private_address_controller.resolve_address_in_host_cache( event.getPeerAddress(), &peer_address_type, &peer_address @@ -2476,7 +2476,7 @@ void Gap::signal_connection_complete( _event_handler->onConnectionComplete(event); } else { bool resolution_pending = false; - ble_error_t ret = _address_registry.queue_resolve_address_on_host(event.getPeerAddress()); + ble_error_t ret = _private_address_controller.queue_resolve_address_on_host(event.getPeerAddress()); if (ret == BLE_ERROR_NONE) { ConnectionCompleteEvent* event_copy = new(std::nothrow) ConnectionCompleteEvent(event); @@ -2532,7 +2532,7 @@ bool Gap::apply_peripheral_privacy_connection_policy( switch (_peripheral_privacy_configuration.resolution_strategy) { case peripheral_privacy_configuration_t::REJECT_NON_RESOLVED_ADDRESS: /* if there is no bond then allow unresolved addresses */ - if (_address_registry.read_resolving_list_size() == 0) { + if (_private_address_controller.read_resolving_list_size() == 0) { return true; } _pal_gap.disconnect( @@ -2576,7 +2576,7 @@ void Gap::conclude_signal_connection_complete_after_address_resolution( if (identity_address) { /* move old address to resolvable address */ event.setPeerResolvablePrivateAddress(event.getPeerAddress()); - event.setLocalResolvablePrivateAddress(_address_registry.get_resolvable_private_address()); + event.setLocalResolvablePrivateAddress(_private_address_controller.get_resolvable_private_address()); event.setPeerAddress(*identity_address); event.setPeerAddressType(identity_address_type == target_peer_address_type_t::RANDOM ? @@ -2616,7 +2616,7 @@ void Gap::signal_advertising_report( const address_t *peer_address = nullptr; target_peer_address_type_t peer_address_type(target_peer_address_type_t::RANDOM); - address_resolved = _address_registry.resolve_address_in_host_cache( + address_resolved = _private_address_controller.resolve_address_in_host_cache( event.getPeerAddress(), &peer_address_type, &peer_address @@ -2663,7 +2663,7 @@ void Gap::signal_advertising_report( /* if there is already an item with the same address pending don't kick off resolution*/ if (!duplicate_pending_event) { - ret = _address_registry.queue_resolve_address_on_host(event.getPeerAddress()); + ret = _private_address_controller.queue_resolve_address_on_host(event.getPeerAddress()); } if (ret == BLE_ERROR_NONE) { @@ -2678,7 +2678,7 @@ void Gap::signal_advertising_report( } #else /* filter out unresolved address if at least one bond exists */ - if (_address_registry.read_resolving_list_size() > 0 && + if (_private_address_controller.read_resolving_list_size() > 0 && _central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && event.getPeerAddressType() != peer_address_type_t::PUBLIC && is_random_private_resolvable_address(event.getPeerAddress())) { @@ -2724,7 +2724,7 @@ void Gap::conclude_signal_advertising_report_after_address_resolution( event.setPeerAddressType(peer_address_type); } else if (_central_privacy_configuration.resolution_strategy == central_privacy_configuration_t::RESOLVE_AND_FILTER && - _address_registry.read_resolving_list_size() > 0) { + _private_address_controller.read_resolving_list_size() > 0) { /* filter out unresolved address if at least one bond exists */ return; } @@ -3333,8 +3333,8 @@ void Gap::on_private_address_generated(bool connectable) } if (_privacy_initialization_pending && - _address_registry.get_resolvable_private_address() != address_t{} && - _address_registry.get_non_resolvable_private_address() != address_t{} + _private_address_controller.get_resolvable_private_address() != address_t{} && + _private_address_controller.get_non_resolvable_private_address() != address_t{} ) { _privacy_initialization_pending = false; if (_event_handler) { @@ -3475,8 +3475,8 @@ const address_t *Gap::get_random_address(controller_operation_t operation, size_ } #if BLE_FEATURE_PRIVACY - const auto &resolvable_address = _address_registry.get_resolvable_private_address(); - const auto &non_resolvable_address = _address_registry.get_non_resolvable_private_address(); + const auto &resolvable_address = _private_address_controller.get_resolvable_private_address(); + const auto &non_resolvable_address = _private_address_controller.get_non_resolvable_private_address(); #if BLE_ROLE_OBSERVER bool central_non_resolvable = _central_privacy_configuration.use_non_resolvable_random_address; diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index dc0d5cec57..59dc5f1c19 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -555,7 +555,7 @@ private: ble::PalGap &pal_gap, ble::PalGenericAccessService &generic_access_service #if BLE_FEATURE_PRIVACY - , ble::PrivateAddressController &pal_addr_reg + , ble::PrivateAddressController &private_address_controller #endif // BLE_FEATURE_PRIVACY ); @@ -874,7 +874,7 @@ private: PalGap &_pal_gap; PalGenericAccessService &_gap_service; #if BLE_FEATURE_PRIVACY - PrivateAddressController &_address_registry; + PrivateAddressController &_private_address_controller; #endif // BLE_FEATURE_PRIVACY ble::own_address_type_t _address_type; initiator_policy_t _initiator_policy_mode; From 119d4593616b14bed12a7018d8129aeac942e934 Mon Sep 17 00:00:00 2001 From: Paul Szczeanek Date: Wed, 14 Oct 2020 09:58:11 +0100 Subject: [PATCH 63/63] fix removed friend function --- connectivity/FEATURE_BLE/source/generic/GapImpl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/connectivity/FEATURE_BLE/source/generic/GapImpl.h b/connectivity/FEATURE_BLE/source/generic/GapImpl.h index 59dc5f1c19..91ec155a84 100644 --- a/connectivity/FEATURE_BLE/source/generic/GapImpl.h +++ b/connectivity/FEATURE_BLE/source/generic/GapImpl.h @@ -65,9 +65,7 @@ class Gap : #endif //BLE_FEATURE_PRIVACY { friend PalConnectionMonitor; -#if BLE_FEATURE_PRIVACY friend PalGapEventHandler; -#endif //BLE_FEATURE_PRIVACY friend PalGap; friend impl::BLEInstanceBase;