Skip to content

Commit 2e233a9

Browse files
author
Cruz Monrreal
authored
Merge pull request #7210 from pan-/fix-nordic-security-cancellation
Fix nordic security cancellation
2 parents ea47342 + 4b8fb0b commit 2e233a9

File tree

8 files changed

+245
-47
lines changed

8 files changed

+245
-47
lines changed

features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ nRF5xGap::nRF5xGap() : Gap(),
104104
_privacy_enabled(false),
105105
_peripheral_privacy_configuration(default_peripheral_privacy_configuration),
106106
_central_privacy_configuration(default_central_privacy_configuration),
107-
_non_private_address_type(LegacyAddressType::RANDOM_STATIC)
107+
_non_private_address_type(LegacyAddressType::RANDOM_STATIC),
108+
_connections_role()
108109
{
109110
m_connectionHandle = BLE_CONN_HANDLE_INVALID;
110111
}
@@ -682,6 +683,8 @@ ble_error_t nRF5xGap::reset(void)
682683
/* Clear the internal whitelist */
683684
whitelistAddressesSize = 0;
684685

686+
/* Reset existing mapping between a connection and its role */
687+
release_all_connections_role();
685688

686689
return BLE_ERROR_NONE;
687690
}
@@ -1195,6 +1198,8 @@ void nRF5xGap::processDisconnectionEvent(
11951198
Handle_t handle,
11961199
DisconnectionReason_t reason
11971200
) {
1201+
release_connection_role(handle);
1202+
11981203
if (_connection_event_handler) {
11991204
_connection_event_handler->on_disconnected(
12001205
handle,
@@ -1214,6 +1219,9 @@ void nRF5xGap::on_connection(Gap::Handle_t handle, const ble_gap_evt_connected_t
12141219
// set the new connection handle as the _default_ handle in gap
12151220
setConnectionHandle(handle);
12161221

1222+
// add the connection and the role of the device in the local table
1223+
allocate_connection_role(handle, static_cast<Role_t>(evt.role));
1224+
12171225
// deal with own address
12181226
LegacyAddressType_t own_addr_type;
12191227
Address_t own_address;
@@ -1375,5 +1383,45 @@ void nRF5xGap::on_advertising_packet(const ble_gap_evt_adv_report_t &evt) {
13751383
);
13761384
}
13771385

1386+
ble_error_t nRF5xGap::get_role(ble::connection_handle_t connection, Role_t& role) {
1387+
for (size_t i = 0; i < max_connections_count; ++i) {
1388+
connection_role_t& c = _connections_role[i];
1389+
if (c.is_allocated && c.connection == connection) {
1390+
role = c.is_peripheral ? PERIPHERAL : CENTRAL;
1391+
return BLE_ERROR_NONE;
1392+
}
1393+
}
1394+
1395+
return BLE_ERROR_INVALID_PARAM;
1396+
}
13781397

1398+
void nRF5xGap::allocate_connection_role(
1399+
ble::connection_handle_t connection,
1400+
Role_t role
1401+
) {
1402+
for (size_t i = 0; i < max_connections_count; ++i) {
1403+
connection_role_t& c = _connections_role[i];
1404+
if (c.is_allocated == false) {
1405+
c.connection = connection;
1406+
c.is_peripheral = (role == Gap::PERIPHERAL);
1407+
c.is_allocated = true;
1408+
return;
1409+
}
1410+
}
1411+
}
1412+
void nRF5xGap::release_connection_role(ble::connection_handle_t connection) {
1413+
for (size_t i = 0; i < max_connections_count; ++i) {
1414+
connection_role_t& c = _connections_role[i];
1415+
if (c.is_allocated && c.connection == connection) {
1416+
c.is_allocated = false;
1417+
return;
1418+
}
1419+
}
1420+
}
1421+
1422+
void nRF5xGap::release_all_connections_role() {
1423+
for (size_t i = 0; i < max_connections_count; ++i) {
1424+
_connections_role[i].is_allocated = false;
1425+
}
1426+
}
13791427

features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xGap.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,26 @@ class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor {
259259
DisconnectionReason_t reason
260260
);
261261

262+
/**
263+
* Return the role of the local peripheral for a given connection.
264+
*
265+
* @param[in] connection The connection queried.
266+
* @param[out] role The role of the local device in the connection.
267+
*
268+
* @return BLE_ERROR_NONE in case of success or an appropriate error code.
269+
*/
270+
ble_error_t get_role(ble::connection_handle_t connection, Role_t& role);
271+
262272
private:
263273
friend void btle_handler(ble_evt_t *p_ble_evt);
264274

265275
void on_connection(Handle_t handle, const ble_gap_evt_connected_t& evt);
266276
void on_advertising_packet(const ble_gap_evt_adv_report_t &evt);
267277

278+
void allocate_connection_role(ble::connection_handle_t, Role_t);
279+
void release_connection_role(ble::connection_handle_t);
280+
void release_all_connections_role();
281+
268282
uint16_t m_connectionHandle;
269283

270284
ConnectionEventMonitor::EventHandler* _connection_event_handler;
@@ -275,6 +289,23 @@ class nRF5xGap : public ::Gap, public ble::pal::ConnectionEventMonitor {
275289
AddressType_t _non_private_address_type;
276290
Address_t _non_private_address;
277291

292+
struct connection_role_t {
293+
connection_role_t() :
294+
connection(),
295+
is_peripheral(false),
296+
is_allocated(false)
297+
{ }
298+
299+
ble::connection_handle_t connection;
300+
uint8_t is_peripheral:1;
301+
uint8_t is_allocated:1;
302+
};
303+
304+
static const size_t max_connections_count =
305+
NRF_SDH_BLE_PERIPHERAL_LINK_COUNT + NRF_SDH_BLE_CENTRAL_LINK_COUNT;
306+
307+
connection_role_t _connections_role[max_connections_count];
308+
278309
/*
279310
* Allow instantiation from nRF5xn when required.
280311
*/

features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xPalSecurityManager.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
#include <stdint.h>
1818
#include "nRF5xPalSecurityManager.h"
19+
#include "nRF5xn.h"
20+
#include "ble/Gap.h"
21+
#include "nRF5xGap.h"
1922
#include "nrf_ble.h"
2023
#include "nrf_ble_gap.h"
2124
#include "nrf_soc.h"
@@ -297,6 +300,9 @@ ble_error_t nRF5xSecurityManager::send_pairing_response(
297300
) {
298301
pairing_control_block_t* pairing_cb = allocate_pairing_cb(connection);
299302
if (!pairing_cb) {
303+
// not enough memory; try to reject the pairing request instead of
304+
// waiting for timeout.
305+
cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON);
300306
return BLE_ERROR_NO_MEM;
301307
}
302308
pairing_cb->role = PAIRING_RESPONDER;
@@ -339,22 +345,33 @@ ble_error_t nRF5xSecurityManager::send_pairing_response(
339345
ble_error_t nRF5xSecurityManager::cancel_pairing(
340346
connection_handle_t connection, pairing_failure_t reason
341347
) {
342-
// this is the default path except when a key is expected to be entered by
343-
// the user.
344-
uint32_t err = sd_ble_gap_sec_params_reply(
345-
connection,
346-
reason.value() | 0x80,
347-
/* sec params */ NULL,
348-
/* keyset */ NULL
349-
);
348+
uint32_t err = 0;
350349

351-
if (!err) {
352-
return BLE_ERROR_NONE;
353-
}
350+
pairing_control_block_t* pairing_cb = get_pairing_cb(connection);
354351

355-
// Failed because we're in the wrong state; try to cancel pairing with
356-
// sd_ble_gap_auth_key_reply
357-
if (err == NRF_ERROR_INVALID_STATE) {
352+
// If there is no control block yet then if the local device is a central
353+
// then we must reject the security request otherwise it is a response to
354+
// a pairing feature exchange from a central.
355+
if (!pairing_cb) {
356+
::Gap::Role_t current_role;
357+
if (nRF5xn::Instance().getGap().get_role(connection, current_role) != BLE_ERROR_NONE) {
358+
return BLE_ERROR_INVALID_PARAM;
359+
}
360+
361+
if (current_role == ::Gap::PERIPHERAL) {
362+
// response to a pairing feature request
363+
err = sd_ble_gap_sec_params_reply(
364+
connection,
365+
reason.value() | 0x80,
366+
/* sec params */ NULL,
367+
/* keyset */ NULL
368+
);
369+
} else {
370+
// response to a peripheral security request
371+
err = sd_ble_gap_authenticate(connection, NULL);
372+
}
373+
} else {
374+
// At this point this must be a response to a key
358375
err = sd_ble_gap_auth_key_reply(
359376
connection,
360377
/* key type */ BLE_GAP_AUTH_KEY_TYPE_NONE,

features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF51/source/nRF5xn.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class nRF5xn : public BLEInstanceBase
5555
* always needed in a BLE application. Therefore it is allocated
5656
* statically.
5757
*/
58-
virtual Gap &getGap() {
58+
virtual nRF5xGap &getGap() {
5959
return gapInstance;
6060
};
6161

@@ -134,7 +134,7 @@ class nRF5xn : public BLEInstanceBase
134134
virtual void processEvents();
135135

136136
public:
137-
static nRF5xn& Instance(BLE::InstanceID_t instanceId);
137+
static nRF5xn& Instance(BLE::InstanceID_t instanceId = BLE::DEFAULT_INSTANCE);
138138

139139
private:
140140
bool initialized;

0 commit comments

Comments
 (0)