mirror of https://github.com/ARMmbed/mbed-os.git
Nordic: Port privacy to softdevice v4.
Many things have changed; the identity list isn't shared anymore with the whitelist and resolution is handled by the stack itself.pull/6932/head
parent
6c44a78166
commit
37c036ca6b
|
@ -28,7 +28,6 @@
|
||||||
#include "nRF5xPalSecurityManager.h"
|
#include "nRF5xPalSecurityManager.h"
|
||||||
|
|
||||||
using ble::pal::vendor::nordic::nRF5xSecurityManager;
|
using ble::pal::vendor::nordic::nRF5xSecurityManager;
|
||||||
typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t;
|
|
||||||
using ble::ArrayView;
|
using ble::ArrayView;
|
||||||
using ble::pal::advertising_peer_address_type_t;
|
using ble::pal::advertising_peer_address_type_t;
|
||||||
|
|
||||||
|
@ -316,6 +315,20 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams ¶ms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
adv_para.p_whitelist = &whitelist;
|
adv_para.p_whitelist = &whitelist;
|
||||||
|
#else
|
||||||
|
if (_privacy_enabled) {
|
||||||
|
bool enable_resolution =
|
||||||
|
_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE;
|
||||||
|
update_identities_list(enable_resolution);
|
||||||
|
|
||||||
|
if (_peripheral_privacy_configuration.use_non_resolvable_random_address &&
|
||||||
|
is_advertising_non_connectable(params)
|
||||||
|
) {
|
||||||
|
set_private_non_resolvable_address();
|
||||||
|
} else {
|
||||||
|
set_private_resolvable_address();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
/* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */
|
/* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */
|
||||||
|
|
||||||
|
@ -384,7 +397,13 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams)
|
||||||
scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
|
scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
|
||||||
scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
|
scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
|
||||||
scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
|
scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
|
||||||
|
|
||||||
if (_privacy_enabled) {
|
if (_privacy_enabled) {
|
||||||
|
bool enable_resolution =
|
||||||
|
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE;
|
||||||
|
|
||||||
|
update_identities_list(enable_resolution);
|
||||||
|
|
||||||
if (_central_privacy_configuration.use_non_resolvable_random_address) {
|
if (_central_privacy_configuration.use_non_resolvable_random_address) {
|
||||||
set_private_non_resolvable_address();
|
set_private_non_resolvable_address();
|
||||||
} else {
|
} else {
|
||||||
|
@ -525,6 +544,14 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr,
|
||||||
addr.addr_id_peer = 0;
|
addr.addr_id_peer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_privacy_enabled) {
|
||||||
|
bool enable_resolution =
|
||||||
|
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE;
|
||||||
|
|
||||||
|
update_identities_list(enable_resolution);
|
||||||
|
set_private_resolvable_address();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (scanParamsIn != NULL) {
|
if (scanParamsIn != NULL) {
|
||||||
|
@ -1201,6 +1228,37 @@ void nRF5xGap::processDisconnectionEvent(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ble_error_t nRF5xGap::update_identities_list(bool resolution_enabled)
|
||||||
|
{
|
||||||
|
uint32_t err;
|
||||||
|
|
||||||
|
if (resolution_enabled) {
|
||||||
|
ArrayView<ble_gap_id_key_t> entries = get_sm().get_resolving_list();
|
||||||
|
size_t limit = std::min(
|
||||||
|
entries.size(), (size_t) YOTTA_CFG_IRK_TABLE_MAX_SIZE
|
||||||
|
);
|
||||||
|
ble_gap_id_key_t* id_keys_pp[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < limit; ++i) {
|
||||||
|
id_keys_pp[i] = &entries[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sd_ble_gap_device_identities_set(
|
||||||
|
limit ? id_keys_pp : NULL,
|
||||||
|
/* use the local IRK for all devices */ NULL,
|
||||||
|
limit
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err = sd_ble_gap_device_identities_set(
|
||||||
|
NULL,
|
||||||
|
/* use the local IRK for all devices */ NULL,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err ? BLE_ERROR_INVALID_STATE : BLE_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) {
|
void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t& evt) {
|
||||||
using BLEProtocol::AddressType;
|
using BLEProtocol::AddressType;
|
||||||
|
|
||||||
|
@ -1246,14 +1304,8 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
|
||||||
|
|
||||||
|
|
||||||
if (private_peer_known) {
|
if (private_peer_known) {
|
||||||
// FIXME: Is this correct for SD > 2 ?
|
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);;
|
||||||
const resolving_list_entry_t* entry = get_sm().resolve_address(
|
peer_address = evt.peer_addr.addr;
|
||||||
evt.peer_addr.addr
|
|
||||||
);
|
|
||||||
MBED_ASSERT(entry == NULL);
|
|
||||||
|
|
||||||
peer_addr_type = convert_identity_address(entry->peer_identity_address_type);
|
|
||||||
peer_address = entry->peer_identity_address.data();
|
|
||||||
peer_resolvable_address = evt.peer_addr.addr;
|
peer_resolvable_address = evt.peer_addr.addr;
|
||||||
} else {
|
} else {
|
||||||
if (_privacy_enabled &&
|
if (_privacy_enabled &&
|
||||||
|
@ -1294,7 +1346,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
|
||||||
) {
|
) {
|
||||||
switch (_peripheral_privacy_configuration.resolution_strategy) {
|
switch (_peripheral_privacy_configuration.resolution_strategy) {
|
||||||
case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE:
|
case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE:
|
||||||
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle);
|
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE:
|
case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE:
|
||||||
|
@ -1322,32 +1374,16 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
|
||||||
void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) {
|
void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) {
|
||||||
using BLEProtocol::AddressType;
|
using BLEProtocol::AddressType;
|
||||||
|
|
||||||
AddressType_t peer_addr_type;
|
|
||||||
const uint8_t* peer_address = evt.peer_addr.addr;
|
|
||||||
|
|
||||||
if (_privacy_enabled &&
|
if (_privacy_enabled &&
|
||||||
evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE &&
|
evt.peer_addr.addr_id_peer == 0 &&
|
||||||
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE
|
_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER
|
||||||
) {
|
) {
|
||||||
using ble::pal::vendor::nordic::nRF5xSecurityManager;
|
return;
|
||||||
|
|
||||||
const resolving_list_entry_t* entry = get_sm().resolve_address(
|
|
||||||
peer_address
|
|
||||||
);
|
|
||||||
|
|
||||||
if (entry) {
|
|
||||||
peer_address = entry->peer_identity_address.data();
|
|
||||||
peer_addr_type = convert_identity_address(entry->peer_identity_address_type);
|
|
||||||
} else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) {
|
|
||||||
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
|
|
||||||
} else {
|
|
||||||
// filter out the packet.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddressType_t peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
|
||||||
|
const uint8_t* peer_address = evt.peer_addr.addr;
|
||||||
|
|
||||||
processAdvertisementReport(
|
processAdvertisementReport(
|
||||||
peer_address,
|
peer_address,
|
||||||
evt.rssi,
|
evt.rssi,
|
||||||
|
|
|
@ -267,6 +267,7 @@ private:
|
||||||
friend void btle_handler(const ble_evt_t *p_ble_evt);
|
friend void btle_handler(const ble_evt_t *p_ble_evt);
|
||||||
friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context);
|
friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context);
|
||||||
|
|
||||||
|
ble_error_t update_identities_list(bool resolution_enabled);
|
||||||
void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt);
|
void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt);
|
||||||
void on_advertising_packet(const ble_gap_evt_adv_report_t &evt);
|
void on_advertising_packet(const ble_gap_evt_adv_report_t &evt);
|
||||||
uint16_t m_connectionHandle;
|
uint16_t m_connectionHandle;
|
||||||
|
|
|
@ -158,10 +158,18 @@ ble_error_t nRF5xSecurityManager::add_device_to_resolving_list(
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count];
|
ble_gap_id_key_t& entry = resolving_list[resolving_list_entry_count];
|
||||||
entry.peer_identity_address_type = peer_identity_address_type;
|
entry.id_addr_info.addr_type = peer_identity_address_type.value();
|
||||||
entry.peer_identity_address = peer_identity_address;
|
memcpy(
|
||||||
entry.peer_irk = peer_irk;
|
entry.id_addr_info.addr,
|
||||||
|
peer_identity_address.data(),
|
||||||
|
peer_identity_address.size()
|
||||||
|
);
|
||||||
|
memcpy(
|
||||||
|
entry.id_info.irk,
|
||||||
|
peer_irk.data(),
|
||||||
|
peer_irk.size()
|
||||||
|
);
|
||||||
|
|
||||||
++resolving_list_entry_count;
|
++resolving_list_entry_count;
|
||||||
|
|
||||||
|
@ -176,9 +184,9 @@ ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list(
|
||||||
|
|
||||||
// first the index needs to be found
|
// first the index needs to be found
|
||||||
for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) {
|
for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) {
|
||||||
resolving_list_entry_t& entry = resolving_list[entry_index];
|
ble_gap_id_key_t& entry = resolving_list[entry_index];
|
||||||
if (entry.peer_identity_address_type == peer_identity_address_type &&
|
if (entry.id_addr_info.addr_type == peer_identity_address_type.value() &&
|
||||||
entry.peer_identity_address == peer_identity_address
|
entry.id_addr_info.addr == peer_identity_address
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -204,46 +212,13 @@ ble_error_t nRF5xSecurityManager::clear_resolving_list()
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayView<nRF5xSecurityManager::resolving_list_entry_t>
|
ArrayView<ble_gap_id_key_t> nRF5xSecurityManager::get_resolving_list() {
|
||||||
nRF5xSecurityManager::get_resolving_list() {
|
return ArrayView<ble_gap_id_key_t>(
|
||||||
return ArrayView<nRF5xSecurityManager::resolving_list_entry_t>(
|
|
||||||
resolving_list,
|
resolving_list,
|
||||||
resolving_list_entry_count
|
resolving_list_entry_count
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nRF5xSecurityManager::resolving_list_entry_t*
|
|
||||||
nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) {
|
|
||||||
#if defined(MBEDTLS_ECDH_C)
|
|
||||||
typedef byte_array_t<CryptoToolbox::hash_size_> hash_t;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < resolving_list_entry_count; ++i) {
|
|
||||||
resolving_list_entry_t& entry = resolving_list[i];
|
|
||||||
hash_t hash_generated;
|
|
||||||
|
|
||||||
// Compute the hash part from the random address part when the irk of
|
|
||||||
// the entry is used
|
|
||||||
_crypto.ah(
|
|
||||||
make_const_ArrayView<CryptoToolbox::irk_size_>(entry.peer_irk),
|
|
||||||
make_const_ArrayView<CryptoToolbox::prand_size_>(
|
|
||||||
resolvable_address.data() + CryptoToolbox::hash_size_
|
|
||||||
),
|
|
||||||
make_ArrayView(hash_generated)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Compare hash generated with the hash present in the address passed as
|
|
||||||
// parameter. If they are equal then the IRK of the entry has been used
|
|
||||||
// to generate the resolvable address.
|
|
||||||
if (memcmp(hash_generated.data(), resolvable_address.data(), CryptoToolbox::hash_size_) == 0) {
|
|
||||||
return &entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Pairing
|
// Pairing
|
||||||
//
|
//
|
||||||
|
|
|
@ -84,39 +84,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ble_error_t clear_resolving_list();
|
virtual ble_error_t clear_resolving_list();
|
||||||
|
|
||||||
/**
|
|
||||||
* An entry of the resolving list stored in the SecurityManager.
|
|
||||||
*/
|
|
||||||
struct resolving_list_entry_t {
|
|
||||||
resolving_list_entry_t() :
|
|
||||||
peer_identity_address_type(
|
|
||||||
advertising_peer_address_type_t::PUBLIC_ADDRESS
|
|
||||||
)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
irk_t peer_irk;
|
|
||||||
address_t peer_identity_address;
|
|
||||||
advertising_peer_address_type_t peer_identity_address_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the IRKs present in the resolving list
|
* Return the IRKs present in the resolving list
|
||||||
* @param count The number of entries present in the resolving list.
|
* @param count The number of entries present in the resolving list.
|
||||||
* @param pointer to the first entry of the resolving list.
|
* @param pointer to the first entry of the resolving list.
|
||||||
*/
|
*/
|
||||||
ArrayView<resolving_list_entry_t> get_resolving_list();
|
ArrayView<ble_gap_id_key_t> get_resolving_list();
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to resolve a private resolvable address.
|
|
||||||
*
|
|
||||||
* @param resolvable_address The address to resolve.
|
|
||||||
*
|
|
||||||
* @return Pointer to the entry found if any.
|
|
||||||
*/
|
|
||||||
const resolving_list_entry_t* resolve_address(
|
|
||||||
const address_t& resolvable_address
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Pairing
|
// Pairing
|
||||||
|
@ -396,7 +369,7 @@ private:
|
||||||
static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT;
|
static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT;
|
||||||
|
|
||||||
size_t resolving_list_entry_count;
|
size_t resolving_list_entry_count;
|
||||||
resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES];
|
ble_gap_id_key_t resolving_list[MAX_RESOLVING_LIST_ENTRIES];
|
||||||
};
|
};
|
||||||
|
|
||||||
} // nordic
|
} // nordic
|
||||||
|
|
Loading…
Reference in New Issue