Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 69 additions & 37 deletions connectivity/FEATURE_BLE/source/generic/GapImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -1859,6 +1862,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);
}

Expand Down Expand Up @@ -2229,7 +2235,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) {
Expand Down Expand Up @@ -2264,6 +2270,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 {
Expand Down Expand Up @@ -2297,15 +2306,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 */
Expand All @@ -2317,42 +2375,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
Expand Down Expand Up @@ -3075,7 +3104,7 @@ void Gap::on_address_resolution_completed(

delete event;
}
#endif BLE_ROLE_OBSERVER
#endif // BLE_ROLE_OBSERVER
#endif // BLE_FEATURE_PRIVACY
}

Expand Down Expand Up @@ -3132,6 +3161,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) {
Expand All @@ -3145,6 +3175,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.
Expand Down
10 changes: 10 additions & 0 deletions connectivity/FEATURE_BLE/source/generic/GapImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,16 @@ class Gap :
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.
Expand Down