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
Vincent Coubard 2018-05-16 14:42:44 +01:00
parent 6c44a78166
commit 37c036ca6b
4 changed files with 89 additions and 104 deletions

View File

@ -28,7 +28,6 @@
#include "nRF5xPalSecurityManager.h"
using ble::pal::vendor::nordic::nRF5xSecurityManager;
typedef nRF5xSecurityManager::resolving_list_entry_t resolving_list_entry_t;
using ble::ArrayView;
using ble::pal::advertising_peer_address_type_t;
@ -316,6 +315,20 @@ ble_error_t nRF5xGap::startAdvertising(const GapAdvertisingParams &params)
}
}
adv_para.p_whitelist = &whitelist;
#else
if (_privacy_enabled) {
bool enable_resolution =
_peripheral_privacy_configuration.resolution_strategy != PeripheralPrivacyConfiguration_t::DO_NOT_RESOLVE;
update_identities_list(enable_resolution);
if (_peripheral_privacy_configuration.use_non_resolvable_random_address &&
is_advertising_non_connectable(params)
) {
set_private_non_resolvable_address();
} else {
set_private_resolvable_address();
}
}
#endif
/* For NRF_SD_BLE_API_VERSION >= 3 nRF5xGap::setWhitelist setups the whitelist. */
@ -384,7 +397,13 @@ ble_error_t nRF5xGap::startRadioScan(const GapScanningParams &scanningParams)
scanParams.interval = scanningParams.getInterval(); /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
scanParams.window = scanningParams.getWindow(); /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
scanParams.timeout = scanningParams.getTimeout(); /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
if (_privacy_enabled) {
bool enable_resolution =
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE;
update_identities_list(enable_resolution);
if (_central_privacy_configuration.use_non_resolvable_random_address) {
set_private_non_resolvable_address();
} else {
@ -524,7 +543,15 @@ ble_error_t nRF5xGap::connect(const Address_t peerAddr,
} else {
addr.addr_id_peer = 0;
}
if (_privacy_enabled) {
bool enable_resolution =
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE;
update_identities_list(enable_resolution);
set_private_resolvable_address();
}
#endif
if (scanParamsIn != NULL) {
@ -1201,6 +1228,37 @@ void nRF5xGap::processDisconnectionEvent(
);
}
ble_error_t nRF5xGap::update_identities_list(bool resolution_enabled)
{
uint32_t err;
if (resolution_enabled) {
ArrayView<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) {
using BLEProtocol::AddressType;
@ -1246,14 +1304,8 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
if (private_peer_known) {
// FIXME: Is this correct for SD > 2 ?
const resolving_list_entry_t* entry = get_sm().resolve_address(
evt.peer_addr.addr
);
MBED_ASSERT(entry == NULL);
peer_addr_type = convert_identity_address(entry->peer_identity_address_type);
peer_address = entry->peer_identity_address.data();
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);;
peer_address = evt.peer_addr.addr;
peer_resolvable_address = evt.peer_addr.addr;
} else {
if (_privacy_enabled &&
@ -1294,7 +1346,7 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
) {
switch (_peripheral_privacy_configuration.resolution_strategy) {
case PeripheralPrivacyConfiguration_t::PERFORM_PAIRING_PROCEDURE:
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestPairing(handle);
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getSecurityManager().requestAuthentication(handle);
break;
case PeripheralPrivacyConfiguration_t::PERFORM_AUTHENTICATION_PROCEDURE:
@ -1322,32 +1374,16 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) {
using BLEProtocol::AddressType;
AddressType_t peer_addr_type;
const uint8_t* peer_address = evt.peer_addr.addr;
if (_privacy_enabled &&
evt.peer_addr.addr_type == BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE &&
_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::DO_NOT_RESOLVE
evt.peer_addr.addr_id_peer == 0 &&
_central_privacy_configuration.resolution_strategy == CentralPrivacyConfiguration_t::RESOLVE_AND_FILTER
) {
using ble::pal::vendor::nordic::nRF5xSecurityManager;
const resolving_list_entry_t* entry = get_sm().resolve_address(
peer_address
);
if (entry) {
peer_address = entry->peer_identity_address.data();
peer_addr_type = convert_identity_address(entry->peer_identity_address_type);
} else if (_central_privacy_configuration.resolution_strategy != CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD) {
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
} else {
// filter out the packet.
return;
}
} else {
peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
return;
}
AddressType_t peer_addr_type = convert_nordic_address(evt.peer_addr.addr_type);
const uint8_t* peer_address = evt.peer_addr.addr;
processAdvertisementReport(
peer_address,
evt.rssi,

View File

@ -267,6 +267,7 @@ private:
friend void btle_handler(const ble_evt_t *p_ble_evt);
friend void btle_handler(const ble_evt_t *p_ble_evt, void *p_context);
ble_error_t update_identities_list(bool resolution_enabled);
void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt);
void on_advertising_packet(const ble_gap_evt_adv_report_t &evt);
uint16_t m_connectionHandle;

View File

@ -158,10 +158,18 @@ ble_error_t nRF5xSecurityManager::add_device_to_resolving_list(
return BLE_ERROR_INVALID_STATE;
}
resolving_list_entry_t& entry = resolving_list[resolving_list_entry_count];
entry.peer_identity_address_type = peer_identity_address_type;
entry.peer_identity_address = peer_identity_address;
entry.peer_irk = peer_irk;
ble_gap_id_key_t& entry = resolving_list[resolving_list_entry_count];
entry.id_addr_info.addr_type = peer_identity_address_type.value();
memcpy(
entry.id_addr_info.addr,
peer_identity_address.data(),
peer_identity_address.size()
);
memcpy(
entry.id_info.irk,
peer_irk.data(),
peer_irk.size()
);
++resolving_list_entry_count;
@ -176,9 +184,9 @@ ble_error_t nRF5xSecurityManager::remove_device_from_resolving_list(
// first the index needs to be found
for (entry_index = 0; entry_index < resolving_list_entry_count; ++entry_index) {
resolving_list_entry_t& entry = resolving_list[entry_index];
if (entry.peer_identity_address_type == peer_identity_address_type &&
entry.peer_identity_address == peer_identity_address
ble_gap_id_key_t& entry = resolving_list[entry_index];
if (entry.id_addr_info.addr_type == peer_identity_address_type.value() &&
entry.id_addr_info.addr == peer_identity_address
) {
break;
}
@ -204,46 +212,13 @@ ble_error_t nRF5xSecurityManager::clear_resolving_list()
return BLE_ERROR_NONE;
}
ArrayView<nRF5xSecurityManager::resolving_list_entry_t>
nRF5xSecurityManager::get_resolving_list() {
return ArrayView<nRF5xSecurityManager::resolving_list_entry_t>(
ArrayView<ble_gap_id_key_t> nRF5xSecurityManager::get_resolving_list() {
return ArrayView<ble_gap_id_key_t>(
resolving_list,
resolving_list_entry_count
);
}
const nRF5xSecurityManager::resolving_list_entry_t*
nRF5xSecurityManager::resolve_address(const address_t& resolvable_address) {
#if defined(MBEDTLS_ECDH_C)
typedef byte_array_t<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
//

View File

@ -84,39 +84,12 @@ public:
*/
virtual ble_error_t clear_resolving_list();
/**
* An entry of the resolving list stored in the SecurityManager.
*/
struct resolving_list_entry_t {
resolving_list_entry_t() :
peer_identity_address_type(
advertising_peer_address_type_t::PUBLIC_ADDRESS
)
{ }
irk_t peer_irk;
address_t peer_identity_address;
advertising_peer_address_type_t peer_identity_address_type;
};
/**
* Return the IRKs present in the resolving list
* @param count The number of entries present in the resolving list.
* @param pointer to the first entry of the resolving list.
*/
ArrayView<resolving_list_entry_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
);
ArrayView<ble_gap_id_key_t> get_resolving_list();
////////////////////////////////////////////////////////////////////////////
// Pairing
@ -396,7 +369,7 @@ private:
static const size_t MAX_RESOLVING_LIST_ENTRIES = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT;
size_t resolving_list_entry_count;
resolving_list_entry_t resolving_list[MAX_RESOLVING_LIST_ENTRIES];
ble_gap_id_key_t resolving_list[MAX_RESOLVING_LIST_ENTRIES];
};
} // nordic