From 1c9ae30d1c70509dd54f3895a05b6de2ed158e17 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Sat, 16 Jan 2016 21:05:46 +0000 Subject: [PATCH] microbit: Added basic bond table management The Nordic BLE stack contains a fixed size bond table - a list of devices that have paired with our device (in the case the micro:bit). The default mbed wrapper around the nordic stack does not account for the case where the bond table is full. This patch implements basic bounds checking within the MicroBitBLEManager so that this table cannot overrun. If a new device attempts to pair when the bond table is full, the table is emptied prior to completing bonding. --- inc/MicroBitBLEManager.h | 6 +++ source/ble-services/MicroBitBLEManager.cpp | 52 ++++++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/inc/MicroBitBLEManager.h b/inc/MicroBitBLEManager.h index baab621..86a38df 100644 --- a/inc/MicroBitBLEManager.h +++ b/inc/MicroBitBLEManager.h @@ -98,6 +98,12 @@ class MicroBitBLEManager */ void advertise(); + /** + * Determines the number of devices currently bonded with this micro:bit + * @return The number of active bonds. + */ + int getBondCount(); + /** * A request to pair has been received from a BLE device. * If we're in pairing mode, display the passkey to the user. diff --git a/source/ble-services/MicroBitBLEManager.cpp b/source/ble-services/MicroBitBLEManager.cpp index 6ec9130..1956ca5 100644 --- a/source/ble-services/MicroBitBLEManager.cpp +++ b/source/ble-services/MicroBitBLEManager.cpp @@ -26,6 +26,7 @@ #define MICROBIT_PAIRING_FADE_SPEED 4 #define MICROBIT_BLE_POWER_LEVELS 8 +#define MICROBIT_BLE_MAXIMUM_BONDS 4 const char* MICROBIT_BLE_MANUFACTURER = "The Cast of W1A"; @@ -142,10 +143,10 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) // Configure a whitelist to filter all connection requetss from unbonded devices. // Most BLE stacks only permit one connection at a time, so this prevents denial of service attacks. - BLEProtocol::Address_t bondedAddresses[4]; + BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS]; Gap::Whitelist_t whitelist; whitelist.addresses = bondedAddresses; - whitelist.capacity = 4; + whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; ble->securityManager().getAddressesFromBondTable(whitelist); ble->gap().setWhitelist(whitelist); @@ -244,13 +245,39 @@ int MicroBitBLEManager::setTransmitPower(int power) return MICROBIT_OK; } +/** + * Determines the number of devices currently bonded with this micro:bit + * @return The number of active bonds. + */ +int MicroBitBLEManager::getBondCount() +{ + BLEProtocol::Address_t bondedAddresses[MICROBIT_BLE_MAXIMUM_BONDS]; + Gap::Whitelist_t whitelist; + whitelist.addresses = bondedAddresses; + whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; + ble->securityManager().getAddressesFromBondTable(whitelist); + + return whitelist.size; +} /** * A request to pair has been received from a BLE device. * If we're in pairing mode, display the passkey to the user. + * Also, purge the binding table if it has reached capacity. */ void MicroBitBLEManager::pairingRequested(ManagedString passKey) { + // Firstly, determine if there is free space in the bonding table. + // If not, clear it out to make room. + + // TODO: It would be much better to implement some sort of LRU/NFU policy here, + // but this isn't currently supported in mbed, so we'd need to layer break... + + // If we're full, empty the bond table. + if (getBondCount() >= MICROBIT_BLE_MAXIMUM_BONDS) + ble->securityManager().purgeAllBondingState(); + + // Update our mode to display the passkey. this->passKey = passKey; this->pairingStatus = MICROBIT_BLE_PAIR_REQUEST; } @@ -283,12 +310,14 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display) int brightness = 255; int fadeDirection = 0; + ble->gap().stopAdvertising(); + // Clear the whitelist (if we have one), so that we're discoverable by all BLE devices. #if CONFIG_ENABLED(MICROBIT_BLE_WHITELIST) - BLEProtocol::Address_t addresses[4]; + BLEProtocol::Address_t addresses[MICROBIT_BLE_MAXIMUM_BONDS]; Gap::Whitelist_t whitelist; whitelist.addresses = addresses; - whitelist.capacity = 4; + whitelist.capacity = MICROBIT_BLE_MAXIMUM_BONDS; whitelist.size = 0; ble->gap().setWhitelist(whitelist); ble->gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); @@ -365,6 +394,21 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display) { MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n"); display.print(tick,0,0,0); + uBit.sleep(5000); + + /* + * Disabled, as the API to return the number of active bonds is not reliable at present... + * + display.clear(); + ManagedString c(getBondCount()); + ManagedString c2("/"); + ManagedString c3(MICROBIT_BLE_MAXIMUM_BONDS); + ManagedString c4("USED"); + + display.scroll(c+c2+c3+c4); + * + * + */ } else {