Skip to content

Commit 3939695

Browse files
committed
Nordic BLE: simplify whitelist management.
1 parent 6810c02 commit 3939695

File tree

2 files changed

+21
-301
lines changed

2 files changed

+21
-301
lines changed

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

Lines changed: 21 additions & 268 deletions
Original file line numberDiff line numberDiff line change
@@ -824,17 +824,33 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn)
824824
}
825825

826826
whitelistAddressesSize = whitelistIn.size;
827+
ble_gap_addr_t* pp_addrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
827828

828829
for (uint32_t i = 0; i < whitelistIn.size; ++i) {
829-
memcpy(&whitelistAddresses[i].addr , &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr));
830+
memcpy(&whitelistAddresses[i].addr, &whitelistIn.addresses[i].address , sizeof(whitelistAddresses[0].addr));
830831
whitelistAddresses[i].addr_type = static_cast<uint8_t> (whitelistIn.addresses[i].type);
832+
pp_addrs[i] = &whitelistAddresses[i];
831833
}
832834

833-
#if (NRF_SD_BLE_API_VERSION >= 3)
834-
updateWhiteAndIdentityListInStack();
835-
#endif
835+
ble_gap_addr_t** addresses_list_ptr = (whitelistIn.size == 0) ? NULL : pp_addrs;
836836

837-
return BLE_ERROR_NONE;
837+
uint32_t err = sd_ble_gap_whitelist_set(addresses_list_ptr, whitelistAddressesSize);
838+
839+
switch(err) {
840+
case NRF_SUCCESS:
841+
return BLE_ERROR_NONE;
842+
843+
case BLE_ERROR_GAP_WHITELIST_IN_USE:
844+
return BLE_ERROR_INVALID_STATE;
845+
846+
case NRF_ERROR_INVALID_ADDR:
847+
case BLE_ERROR_GAP_INVALID_BLE_ADDR:
848+
case NRF_ERROR_DATA_SIZE:
849+
return BLE_ERROR_INVALID_PARAM;
850+
851+
default:
852+
return BLE_ERROR_UNSPECIFIED;
853+
}
838854
}
839855

840856
/**************************************************************************/
@@ -860,7 +876,6 @@ ble_error_t nRF5xGap::setWhitelist(const Gap::Whitelist_t &whitelistIn)
860876
ble_error_t nRF5xGap::setAdvertisingPolicyMode(Gap::AdvertisingPolicyMode_t mode)
861877
{
862878
advertisingPolicyMode = mode;
863-
864879
return BLE_ERROR_NONE;
865880
}
866881

@@ -973,267 +988,5 @@ Gap::InitiatorPolicyMode_t nRF5xGap::getInitiatorPolicyMode(void) const
973988
return Gap::INIT_POLICY_IGNORE_WHITELIST;
974989
}
975990

976-
#if (NRF_SD_BLE_API_VERSION <= 2)
977-
/**************************************************************************/
978-
/*!
979-
@brief Helper function used to populate the ble_gap_whitelist_t that
980-
will be used by the SoftDevice for filtering requests.
981-
982-
@returns \ref ble_error_t
983-
984-
@retval BLE_ERROR_NONE
985-
Everything executed properly
986-
987-
@retval BLE_ERROR_INVALID_STATE
988-
The internal stack was not initialized correctly.
989-
990-
@note Both the SecurityManager and Gap must initialize correctly for
991-
this function to succeed.
992-
993-
@note This function is needed because for the BLE API the whitelist
994-
is just a collection of keys, but for the stack it also includes
995-
the IRK table.
996-
997-
@section EXAMPLE
998-
999-
@code
1000-
1001-
@endcode
1002-
*/
1003-
/**************************************************************************/
1004-
ble_error_t nRF5xGap::generateStackWhitelist(ble_gap_whitelist_t &whitelist)
1005-
{
1006-
ble_gap_whitelist_t whitelistFromBondTable;
1007-
ble_gap_addr_t *addressPtr[1];
1008-
ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
1009-
1010-
nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager();
1011-
1012-
if (securityManager.hasInitialized()) {
1013-
/* We do not care about the addresses, set the count to 0 */
1014-
whitelistFromBondTable.addr_count = 0;
1015-
/* The Nordic SDK will return a failure if we set pp_addr to NULL */
1016-
whitelistFromBondTable.pp_addrs = addressPtr;
1017-
/* We want all the IRKs we can get because we do not know which ones match the addresses */
1018-
whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
1019-
whitelistFromBondTable.pp_irks = irkPtr;
1020-
1021-
/* Use the security manager to get the IRKs from the bond table */
1022-
ble_error_t error = securityManager.createWhitelistFromBondTable(whitelistFromBondTable);
1023-
if (error != BLE_ERROR_NONE) {
1024-
return error;
1025-
}
1026-
} else {
1027-
/**
1028-
* If there is no security manager then we cannot access the bond table,
1029-
* so disable IRK matching
1030-
*/
1031-
whitelistFromBondTable.addr_count = 0;
1032-
whitelistFromBondTable.irk_count = 0;
1033-
}
1034-
1035-
/**
1036-
* For every private resolvable address in the local whitelist check if
1037-
* there is an IRK for said address in the bond table and add it to the
1038-
* local IRK list.
1039-
*/
1040-
whitelist.irk_count = 0;
1041-
whitelist.addr_count = 0;
1042-
for (uint8_t i = 0; i < whitelistAddressesSize; ++i) {
1043-
if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE) {
1044-
/* Test if there is a matching IRK for this private resolvable address */
1045-
for (uint8_t j = 0; j < whitelistFromBondTable.irk_count; ++j) {
1046-
if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], whitelistFromBondTable.pp_irks[j])) {
1047-
/* Found the corresponding IRK, add it to our local whitelist */
1048-
whitelist.pp_irks[whitelist.irk_count] = whitelistFromBondTable.pp_irks[j];
1049-
whitelist.irk_count++;
1050-
/* Make sure we do not look at this IRK again */
1051-
if (j != whitelistFromBondTable.irk_count - 1) {
1052-
/**
1053-
* This is not the last IRK, so replace the pointer
1054-
* with the last pointer in the array
1055-
*/
1056-
whitelistFromBondTable.pp_irks[j] =
1057-
whitelistFromBondTable.pp_irks[whitelistFromBondTable.irk_count - 1];
1058-
}
1059-
/**
1060-
* If the IRK is the last pointer in the array simply
1061-
* decrement the total IRK count
1062-
*/
1063-
whitelistFromBondTable.irk_count--;
1064-
break;
1065-
}
1066-
}
1067-
} else {
1068-
/* Include the address into the whitelist */
1069-
whitelist.pp_addrs[whitelist.addr_count] = &whitelistAddresses[i];
1070-
whitelist.addr_count++;
1071-
}
1072-
}
1073-
1074-
return BLE_ERROR_NONE;
1075-
}
1076-
#endif
1077-
1078-
#if (NRF_SD_BLE_API_VERSION >= 3)
1079-
1080-
/**
1081-
* Function for preparing settings of the whitelist feature and the identity-resolving feature (privacy) for the SoftDevice.
1082-
*
1083-
* Gap::setWhitelist provides the base for preparation of these settings.
1084-
* This function matches resolvable addresses (passed by Gap::setWhitelist) to IRK data in bonds table.
1085-
* Therefore resolvable addresses instead of being passed to the whitelist (intended to be passed to the Softdevice)
1086-
* are passed to the identities list (intended to be passed to the Softdevice).
1087-
*
1088-
* @param[out] gapAdrHelper Reference to the struct for storing settings.
1089-
*/
1090-
1091-
ble_error_t nRF5xGap::getStackWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper)
1092-
{
1093-
pm_peer_id_t peer_id;
1094-
1095-
ret_code_t ret;
1096-
1097-
pm_peer_data_bonding_t bond_data;
1098-
1099-
uint8_t irk_found[YOTTA_CFG_WHITELIST_MAX_SIZE];
1100-
1101-
memset(irk_found, 0x00, sizeof(irk_found));
1102-
1103-
1104-
gapAdrHelper.identities_cnt = 0;
1105-
1106-
1107-
peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
1108-
1109-
nRF5xSecurityManager& securityManager = (nRF5xSecurityManager&) nRF5xn::Instance(0).getSecurityManager();
1110-
1111-
/**
1112-
* Build identities list:
1113-
* For every private resolvable address in the bond table check if
1114-
* there is maching address in th provided whitelist.
1115-
*/
1116-
while (peer_id != PM_PEER_ID_INVALID)
1117-
{
1118-
memset(&bond_data, 0x00, sizeof(bond_data));
1119-
1120-
// Read peer data from flash.
1121-
ret = pm_peer_data_bonding_load(peer_id, &bond_data);
1122-
1123-
1124-
if ((ret == NRF_ERROR_NOT_FOUND) || (ret == NRF_ERROR_INVALID_PARAM))
1125-
{
1126-
// Peer data could not be found in flash or peer ID is not valid.
1127-
return BLE_ERROR_UNSPECIFIED;
1128-
}
1129-
1130-
if ( bond_data.peer_ble_id.id_addr_info.addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE)
1131-
{
1132-
for (uint8_t i = 0; i < whitelistAddressesSize; ++i)
1133-
{
1134-
if (!irk_found[i])
1135-
{
1136-
if (whitelistAddresses[i].addr_type == BLEProtocol::AddressType::RANDOM_PRIVATE_RESOLVABLE)
1137-
{
1138-
1139-
//ble_gap_irk_t *p_dfg = &bond_data.peer_ble_id.id_info;
1140-
if (securityManager.matchAddressAndIrk(&whitelistAddresses[i], &bond_data.peer_ble_id.id_info))
1141-
{
1142-
// Copy data to the buffer.
1143-
memcpy(&gapAdrHelper.identities[i], &bond_data.peer_ble_id, sizeof(ble_gap_id_key_t));
1144-
gapAdrHelper.identities_cnt++;
1145-
1146-
irk_found[i] = 1; // don't look at this address again
1147-
}
1148-
}
1149-
}
1150-
}
1151-
}
1152-
1153-
// get next peer id
1154-
peer_id = pm_next_peer_id_get(peer_id);
1155-
}
1156-
1157-
gapAdrHelper.addrs_cnt = 0;
1158-
1159-
/**
1160-
* Build whitelist from the rest of addresses (explicit addresses)
1161-
*/
1162-
for (uint8_t i = 0; i < whitelistAddressesSize; ++i)
1163-
{
1164-
if (!irk_found[i])
1165-
{
1166-
memcpy(&gapAdrHelper.addrs[i], &whitelistAddresses[i], sizeof(ble_gap_addr_t));
1167-
gapAdrHelper.addrs[i].addr_id_peer = 0;
1168-
gapAdrHelper.addrs_cnt++;
1169-
}
1170-
}
1171-
1172-
return BLE_ERROR_NONE;
1173-
}
1174-
1175-
ble_error_t nRF5xGap::applyWhiteIdentityList(GapWhiteAndIdentityList_t &gapAdrHelper)
1176-
{
1177-
uint32_t retc;
1178-
1179-
if (gapAdrHelper.identities_cnt == 0) {
1180-
retc = sd_ble_gap_device_identities_set(NULL, NULL, 0);
1181-
} else {
1182-
ble_gap_id_key_t * pp_identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
1183-
1184-
for (uint32_t i = 0; i < gapAdrHelper.identities_cnt; ++i)
1185-
{
1186-
pp_identities[i] = &gapAdrHelper.identities[i];
1187-
}
1188-
1189-
retc = sd_ble_gap_device_identities_set(pp_identities, NULL /* Don't use local IRKs*/,gapAdrHelper.identities_cnt);
1190-
}
1191-
1192-
if (retc == NRF_SUCCESS) {
1193-
if (gapAdrHelper.addrs_cnt == 0) {
1194-
retc = sd_ble_gap_whitelist_set(NULL, 0);
1195-
} else {
1196-
ble_gap_addr_t * pp_addrs[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
1197-
1198-
for (uint32_t i = 0; i < gapAdrHelper.addrs_cnt; ++i)
1199-
{
1200-
pp_addrs[i] = &gapAdrHelper.addrs[i];
1201-
}
1202-
1203-
retc = sd_ble_gap_whitelist_set(pp_addrs, gapAdrHelper.addrs_cnt);
1204-
}
1205-
}
1206-
1207-
switch(retc) {
1208-
case NRF_SUCCESS:
1209-
return BLE_ERROR_NONE;
1210991

1211-
case BLE_ERROR_GAP_WHITELIST_IN_USE: //The whitelist is in use by a BLE role and cannot be set or cleared.
1212-
case BLE_ERROR_GAP_DEVICE_IDENTITIES_IN_USE: //The device identity list is in use and cannot be set or cleared.
1213-
return BLE_ERROR_ALREADY_INITIALIZED;
1214992

1215-
case NRF_ERROR_INVALID_ADDR:
1216-
case BLE_ERROR_GAP_INVALID_BLE_ADDR: //Invalid address type is supplied.
1217-
case NRF_ERROR_DATA_SIZE:
1218-
case BLE_ERROR_GAP_DEVICE_IDENTITIES_DUPLICATE: //The device identity list contains multiple entries with the same identity address.
1219-
return BLE_ERROR_INVALID_PARAM;
1220-
1221-
default:
1222-
return BLE_ERROR_UNSPECIFIED;
1223-
}
1224-
}
1225-
1226-
ble_error_t nRF5xGap::updateWhiteAndIdentityListInStack()
1227-
{
1228-
GapWhiteAndIdentityList_t whiteAndIdentityList;
1229-
uint32_t err;
1230-
1231-
err = getStackWhiteIdentityList(whiteAndIdentityList);
1232-
1233-
if (err != BLE_ERROR_NONE) {
1234-
return (ble_error_t)err;
1235-
}
1236-
1237-
return applyWhiteIdentityList(whiteAndIdentityList);
1238-
}
1239-
#endif

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

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -148,39 +148,6 @@ class nRF5xGap : public Gap
148148
uint8_t whitelistAddressesSize;
149149
ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE];
150150

151-
#if (NRF_SD_BLE_API_VERSION <= 2)
152-
/*
153-
* An internal function used to populate the ble_gap_whitelist_t that will be used by
154-
* the SoftDevice for filtering requests. This function is needed because for the BLE
155-
* API the whitelist is just a collection of keys, but for the stack it also includes
156-
* the IRK table.
157-
*/
158-
ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist);
159-
#endif
160-
161-
#if (NRF_SD_BLE_API_VERSION >= 3)
162-
/* internal type for passing a whitelist and a identities list. */
163-
typedef struct
164-
{
165-
ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
166-
uint32_t addrs_cnt;
167-
168-
ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
169-
uint32_t identities_cnt;
170-
} GapWhiteAndIdentityList_t;
171-
172-
/* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/
173-
ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
174-
175-
/* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/
176-
ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
177-
178-
/* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice.
179-
*
180-
* This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */
181-
ble_error_t updateWhiteAndIdentityListInStack(void);
182-
#endif
183-
184151
private:
185152
bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */
186153
Timeout radioNotificationTimeout;

0 commit comments

Comments
 (0)