mirror of https://github.com/ARMmbed/mbed-os.git
363 lines
13 KiB
C++
363 lines
13 KiB
C++
/* 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
|
|
|
|
#if BLE_FEATURE_PRIVACY
|
|
|
|
#include <cstdio>
|
|
|
|
#include "ble/common/BLETypes.h"
|
|
#include "ble/common/blecommon.h"
|
|
#include "source/pal/PalEventQueue.h"
|
|
#include "source/pal/PalPrivateAddressController.h"
|
|
|
|
#ifdef DEVICE_LPTICKER
|
|
#include "drivers/LowPowerTicker.h"
|
|
#else
|
|
#include "drivers/Ticker.h"
|
|
#endif
|
|
|
|
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:
|
|
#ifdef DEVICE_LPTICKER
|
|
using Ticker = mbed::LowPowerTicker;
|
|
#else
|
|
using Ticker = mbed::Ticker;
|
|
#endif
|
|
|
|
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;
|
|
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
/**
|
|
* 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_completed(
|
|
const address_t &peer_resolvable_address,
|
|
bool resolved,
|
|
target_peer_address_type_t identity_address_type,
|
|
const address_t &identity_address
|
|
) = 0;
|
|
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
};
|
|
|
|
/**
|
|
* 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();
|
|
|
|
#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 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.
|
|
* @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();
|
|
|
|
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
/**
|
|
* 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_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_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
|
|
* 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_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.
|
|
*
|
|
* @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_host_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_on_host(const address_t &peer_address);
|
|
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
|
|
private:
|
|
|
|
void generate_resolvable_address();
|
|
|
|
void generate_non_resolvable_address();
|
|
|
|
// 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;
|
|
|
|
// --- 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();
|
|
|
|
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
struct PrivacyResolveAddressOnHost;
|
|
|
|
void restart_resolution_process_on_host();
|
|
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
|
|
// 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);
|
|
|
|
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
|
struct resolving_list_entry_t;
|
|
|
|
template<typename Pred>
|
|
void remove_resolution_entry_from_cache(const Pred& predicate);
|
|
|
|
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;
|
|
ble::resolvable_address_timeout_t _rotation_timeout;
|
|
bool _generation_started;
|
|
irk_t _local_irk = {};
|
|
EventHandler *_event_handler = nullptr;
|
|
Ticker _address_rotation_ticker;
|
|
address_t _resolvable_address = {};
|
|
address_t _non_resolvable_address = {};
|
|
|
|
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 = {};
|
|
irk_t peer_irk = {};
|
|
target_peer_address_type_t peer_address_type = target_peer_address_type_t::PUBLIC;
|
|
bool populated = false;
|
|
};
|
|
|
|
resolving_list_entry_t _resolving_list[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
|
|
|
struct resolution_entry_t {
|
|
address_t address = address_t {};
|
|
resolution_entry_t *next = nullptr;
|
|
resolving_list_entry_t *identity = nullptr;
|
|
};
|
|
|
|
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
|
|
};
|
|
|
|
}
|
|
|
|
#endif // BLE_FEATURE_PRIVACY
|
|
|
|
#endif //BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H
|