mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #13717 from ARMmbed/feature-ble-host-privacy
Feature ble host privacypull/13745/head
commit
75f3b6cb1c
|
@ -314,6 +314,17 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when advertising starts.
|
||||
*
|
||||
* @param event Advertising start event.
|
||||
*
|
||||
* @see startAdvertising()
|
||||
*/
|
||||
virtual void onAdvertisingStart(const AdvertisingStartEvent &event)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when advertising ends.
|
||||
*
|
||||
|
@ -538,6 +549,14 @@ public:
|
|||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Function invoked when the privacy subsystem has been enabled and is
|
||||
* ready to be used.
|
||||
*/
|
||||
virtual void onPrivacyEnabled()
|
||||
{
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* Prevent polymorphic deletion and avoid unnecessary virtual destructor
|
||||
|
@ -724,6 +743,7 @@ public:
|
|||
* @param maxEvents Max number of events produced during advertising - 0 means no limit.
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*
|
||||
* @see EventHandler::onAdvertisingStart when the advertising starts.
|
||||
* @see EventHandler::onScanRequestReceived when a scan request is received.
|
||||
* @see EventHandler::onAdvertisingEnd when the advertising ends.
|
||||
* @see EventHandler::onConnectionComplete when the device gets connected
|
||||
|
@ -1244,6 +1264,14 @@ public:
|
|||
* resolved and advertisement packets are forwarded to the application
|
||||
* even if the advertiser private address is unknown.
|
||||
*
|
||||
* @par Initialization of the privacy subsystem
|
||||
*
|
||||
* When privacy is enabled, the system generates new resolvable and non
|
||||
* resolvable private addresses. Scan, Advertising and Connecting to a peer
|
||||
* won't be available until the generation process completes. When addresses
|
||||
* have been generated, the application is notified that privacy
|
||||
* initialisation as completed with a call to EventHandler::onPrivacyEnabled .
|
||||
*
|
||||
* @param[in] enable Should be set to true to enable the privacy mode and
|
||||
* false to disable it.
|
||||
*
|
||||
|
@ -1448,6 +1476,8 @@ public:
|
|||
* forbidden by the Bluetooth specification.
|
||||
*/
|
||||
ble_error_t setRandomStaticAddress(const ble::address_t& address);
|
||||
|
||||
ble::address_t getRandomStaticAddress();
|
||||
#endif // !defined(DOXYGEN_ONLY)
|
||||
|
||||
private:
|
||||
|
|
|
@ -835,6 +835,7 @@ public:
|
|||
// Privacy
|
||||
//
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
/**
|
||||
* Sets how often the address is rotated when privacy is enabled.
|
||||
*
|
||||
|
@ -845,6 +846,7 @@ public:
|
|||
ble_error_t setPrivateAddressTimeout(
|
||||
uint16_t timeout_in_seconds
|
||||
);
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
/* Event callback handlers. */
|
||||
public:
|
||||
|
|
|
@ -33,10 +33,11 @@ namespace ble {
|
|||
* @tparam Min left-bound
|
||||
* @tparam Max right-bound
|
||||
*/
|
||||
template<uint32_t Min, uint32_t Max>
|
||||
template<uint32_t Min, uint32_t Max, uint32_t Default = Min>
|
||||
struct Range {
|
||||
static const uint32_t MIN = Min;
|
||||
static const uint32_t MAX = Max;
|
||||
static const uint32_t DEFAULT = Default;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -111,7 +112,7 @@ struct Duration {
|
|||
*
|
||||
* It is initialized with the minimum value acceptable.
|
||||
*/
|
||||
Duration() : duration(Range::MIN)
|
||||
Duration() : duration(Range::DEFAULT)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -598,11 +599,14 @@ bool operator>(Duration<Rep, Us, Range, F> lhs, Duration<Rep, Us, Range, F> rhs)
|
|||
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
|
||||
template<uint32_t Min, uint32_t Max>
|
||||
const uint32_t Range<Min, Max>::MIN;
|
||||
template<uint32_t Min, uint32_t Max, uint32_t Default>
|
||||
const uint32_t Range<Min, Max, Default>::MIN;
|
||||
|
||||
template<uint32_t Min, uint32_t Max>
|
||||
const uint32_t Range<Min, Max>::MAX;
|
||||
template<uint32_t Min, uint32_t Max, uint32_t Default>
|
||||
const uint32_t Range<Min, Max, Default>::MAX;
|
||||
|
||||
template<uint32_t Min, uint32_t Max, uint32_t Default>
|
||||
const uint32_t Range<Min, Max, Default>::DEFAULT;
|
||||
|
||||
template<typename T, T V>
|
||||
const T Value<T, V>::VALUE;
|
||||
|
|
|
@ -69,15 +69,15 @@ struct AdvertisingReportEvent {
|
|||
const address_t &directAddress,
|
||||
const mbed::Span<const uint8_t> &advertisingData
|
||||
) :
|
||||
peerAddress(peerAddress),
|
||||
type(type),
|
||||
peerAddressType(peerAddressType),
|
||||
peerAddress(peerAddress),
|
||||
primaryPhy(primaryPhy),
|
||||
secondaryPhy(secondaryPhy),
|
||||
SID(SID),
|
||||
txPower(txPower),
|
||||
rssi(rssi),
|
||||
periodicInterval(periodicInterval),
|
||||
rssi(rssi),
|
||||
directAddressType(directAddressType),
|
||||
directAddress(directAddress),
|
||||
advertisingData(advertisingData)
|
||||
|
@ -85,7 +85,6 @@ struct AdvertisingReportEvent {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Get event type. */
|
||||
const advertising_event_t &getType() const
|
||||
{
|
||||
|
@ -163,18 +162,44 @@ struct AdvertisingReportEvent {
|
|||
return advertisingData;
|
||||
}
|
||||
|
||||
/** Set peer address. */
|
||||
void setPeerAddress(
|
||||
const address_t &newPeerAddress
|
||||
)
|
||||
{
|
||||
peerAddress = newPeerAddress;
|
||||
}
|
||||
|
||||
|
||||
/** Set peer address type. */
|
||||
void setPeerAddressType(
|
||||
const peer_address_type_t &newPeerAddressType
|
||||
)
|
||||
{
|
||||
peerAddressType = newPeerAddressType;
|
||||
}
|
||||
|
||||
/** Set new advertising payload. */
|
||||
void setAdvertisingData(
|
||||
const mbed::Span<const uint8_t> &newAdvertisingData
|
||||
)
|
||||
{
|
||||
advertisingData = newAdvertisingData;
|
||||
}
|
||||
|
||||
private:
|
||||
address_t peerAddress;
|
||||
advertising_event_t type;
|
||||
peer_address_type_t peerAddressType;
|
||||
address_t const &peerAddress;
|
||||
phy_t primaryPhy;
|
||||
phy_t secondaryPhy;
|
||||
advertising_sid_t SID;
|
||||
advertising_power_t txPower;
|
||||
rssi_t rssi;
|
||||
uint16_t periodicInterval;
|
||||
rssi_t rssi;
|
||||
peer_address_type_t directAddressType;
|
||||
const address_t &directAddress;
|
||||
address_t directAddress;
|
||||
ble_error_t status;
|
||||
mbed::Span<const uint8_t> advertisingData;
|
||||
};
|
||||
|
||||
|
@ -215,12 +240,12 @@ struct ConnectionCompleteEvent {
|
|||
) :
|
||||
status(status),
|
||||
connectionHandle(connectionHandle),
|
||||
peerAddress(peerAddress),
|
||||
ownRole(ownRole),
|
||||
peerAddressType(peerAddressType),
|
||||
peerAddress(peerAddress),
|
||||
localResolvablePrivateAddress(localResolvablePrivateAddress),
|
||||
peerResolvablePrivateAddress(peerResolvablePrivateAddress),
|
||||
connectionInterval(connectionInterval),
|
||||
peerResolvablePrivateAddress(peerResolvablePrivateAddress),
|
||||
connectionLatency(connectionLatency),
|
||||
supervisionTimeout(supervisionTimeout),
|
||||
masterClockAccuracy(masterClockAccuracy)
|
||||
|
@ -295,15 +320,46 @@ struct ConnectionCompleteEvent {
|
|||
return masterClockAccuracy;
|
||||
}
|
||||
|
||||
|
||||
/** Set connection complete event status. */
|
||||
void setStatus(ble_error_t new_status)
|
||||
{
|
||||
status = new_status;
|
||||
}
|
||||
|
||||
/** Set peer address type. */
|
||||
void setPeerAddressType(const peer_address_type_t& address_type)
|
||||
{
|
||||
peerAddressType = address_type;
|
||||
}
|
||||
|
||||
/** Set peer address. */
|
||||
void setPeerAddress(const address_t &address)
|
||||
{
|
||||
peerAddress = address;
|
||||
}
|
||||
|
||||
/** Set get local resolvable random address if privacy is used. */
|
||||
void setLocalResolvablePrivateAddress(const address_t &address)
|
||||
{
|
||||
localResolvablePrivateAddress = address;
|
||||
}
|
||||
|
||||
/** Set peer resolvable private address if privacy is used. */
|
||||
void setPeerResolvablePrivateAddress(const address_t &address)
|
||||
{
|
||||
peerResolvablePrivateAddress = address;
|
||||
}
|
||||
|
||||
private:
|
||||
ble_error_t status;
|
||||
connection_handle_t connectionHandle;
|
||||
address_t peerAddress;
|
||||
connection_role_t ownRole;
|
||||
peer_address_type_t peerAddressType;
|
||||
const address_t &peerAddress;
|
||||
const address_t &localResolvablePrivateAddress;
|
||||
const address_t &peerResolvablePrivateAddress;
|
||||
address_t localResolvablePrivateAddress;
|
||||
conn_interval_t connectionInterval;
|
||||
address_t peerResolvablePrivateAddress;
|
||||
slave_latency_t connectionLatency;
|
||||
supervision_timeout_t supervisionTimeout;
|
||||
uint16_t masterClockAccuracy;
|
||||
|
@ -519,15 +575,47 @@ private:
|
|||
*/
|
||||
struct ScanTimeoutEvent { };
|
||||
|
||||
/**
|
||||
* Event produced when advertising start.
|
||||
*
|
||||
* @see ble::Gap::EventHandler::onAdvertisingStart().
|
||||
*/
|
||||
struct AdvertisingStartEvent {
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
|
||||
/** Create an advertising start event.
|
||||
*
|
||||
* @param advHandle Advertising set handle.
|
||||
*/
|
||||
AdvertisingStartEvent(advertising_handle_t advHandle) :
|
||||
advHandle(advHandle)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Get advertising handle. */
|
||||
advertising_handle_t getAdvHandle() const
|
||||
{
|
||||
return advHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_handle_t advHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Event produced when advertising ends.
|
||||
*
|
||||
* @see ble::Gap::EventHandler::onAdvertisingEnd().
|
||||
*
|
||||
* @note The connection handle, connected flag and completed_event fields are
|
||||
* valid if the flag legacy is not set to true.
|
||||
*/
|
||||
struct AdvertisingEndEvent {
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
|
||||
/** Create advertising end event.
|
||||
/** Create an extended advertising end event.
|
||||
*
|
||||
* @param advHandle Advertising set handle.
|
||||
* @param connection Connection handle.
|
||||
|
@ -543,7 +631,19 @@ struct AdvertisingEndEvent {
|
|||
advHandle(advHandle),
|
||||
connection(connection),
|
||||
completed_events(completed_events),
|
||||
connected(connected)
|
||||
connected(connected),
|
||||
legacy(false)
|
||||
{
|
||||
}
|
||||
|
||||
/** Create a legacy advertising end event.
|
||||
*/
|
||||
AdvertisingEndEvent() :
|
||||
advHandle(LEGACY_ADVERTISING_HANDLE),
|
||||
connection(),
|
||||
completed_events(0),
|
||||
connected(false),
|
||||
legacy(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -573,11 +673,22 @@ struct AdvertisingEndEvent {
|
|||
return connected;
|
||||
}
|
||||
|
||||
/** Is the end of legacy advertising.
|
||||
*
|
||||
* If it is the return of getConnection() getCompleted_events() and isConnected()
|
||||
* must be discarded
|
||||
*/
|
||||
bool isLegacy() const
|
||||
{
|
||||
return legacy;
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_handle_t advHandle;
|
||||
connection_handle_t connection;
|
||||
uint8_t completed_events;
|
||||
bool connected;
|
||||
bool legacy;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -121,6 +121,16 @@ typedef Duration<uint16_t, 10000, Range<0x0A, 0x4000> > sync_timeout_t;
|
|||
*/
|
||||
typedef Duration<uint16_t, 1250, Range<0x06, 0xFFFF> > periodic_interval_t;
|
||||
|
||||
/**
|
||||
* Resolvable address timeout.
|
||||
*
|
||||
* The duration is in seconds and ranges from 1 to 0xA1B8. The default value is
|
||||
* 900 seconds.
|
||||
*/
|
||||
using resolvable_address_timeout_t = Duration<
|
||||
uint16_t, second_t::TIME_BASE, Range<1, 0xA1B8, 0x0384>
|
||||
>;
|
||||
|
||||
/**
|
||||
* Number of connection events that can be skipped by the slave.
|
||||
*
|
||||
|
@ -445,8 +455,8 @@ struct scanning_filter_policy_t : SafeEnum<scanning_filter_policy_t, uint8_t> {
|
|||
NO_FILTER = 0x00,
|
||||
|
||||
/**
|
||||
* Accept only advertising packets from devices in the whitelist except
|
||||
* directed advertising packets not addressed to this device.
|
||||
* Accept only advertising packets from devices in the whitelist.
|
||||
* Directed advertising packets not addressed to this device will be ignored.
|
||||
*/
|
||||
FILTER_ADVERTISING = 0x01,
|
||||
|
||||
|
|
|
@ -3035,6 +3035,18 @@ void DmSecSetLocalCsrk(uint8_t *pCsrk);
|
|||
/*************************************************************************************************/
|
||||
void DmSecSetLocalIrk(uint8_t *pIrk);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief This function sets the local identity address used by the device.
|
||||
*
|
||||
* \param pAddr Pointer to the address.
|
||||
* \param type Type of the address.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief This function generates an ECC key for use with LESC security.
|
||||
|
@ -3345,6 +3357,25 @@ uint8_t *DmSecGetLocalCsrk(void);
|
|||
/*************************************************************************************************/
|
||||
uint8_t *DmSecGetLocalIrk(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief For internal use only. This function gets the local identity address used by the device.
|
||||
*
|
||||
* \return Pointer to the identity address.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t *DmSecGetLocalIdentityAddr(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief For internal use only. This function gets the local identity address type used by the
|
||||
* device.
|
||||
*
|
||||
* \return The identity address type.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t DmSecGetLocalIdentityAddrType(void);
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief For internal use only. Read the features of the remote device.
|
||||
|
|
|
@ -329,6 +329,7 @@ void DmSecInit(void)
|
|||
dmFcnIfTbl[DM_ID_SEC] = (dmFcnIf_t *) &dmSecFcnIf;
|
||||
|
||||
dmSecCb.pCsrk = dmSecCb.pIrk = (uint8_t *) calc128Zeros;
|
||||
dmSecCb.addrType = DM_ADDR_NONE;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
@ -363,6 +364,24 @@ void DmSecSetLocalIrk(uint8_t *pIrk)
|
|||
WsfTaskUnlock();
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief This function sets the local identity address used by the device.
|
||||
*
|
||||
* \param pAddr Pointer to the address.
|
||||
* \param type Type of the address.
|
||||
*
|
||||
* \return None.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
void DmSecSetLocalIdentityAddr(const uint8_t *pAddr, uint8_t type)
|
||||
{
|
||||
WsfTaskLock();
|
||||
dmSecCb.addrType = type;
|
||||
BdaCpy(dmSecCb.bdAddr, pAddr);
|
||||
WsfTaskUnlock();
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief This function gets the local CSRK used by the device.
|
||||
|
@ -387,6 +406,39 @@ uint8_t *DmSecGetLocalIrk(void)
|
|||
return dmSecCb.pIrk;
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief For internal use only. This function gets the local identity address used by the device.
|
||||
*
|
||||
* \return Pointer to the identity address.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t *DmSecGetLocalIdentityAddr(void)
|
||||
{
|
||||
if (dmSecCb.addrType != DM_ADDR_NONE) {
|
||||
return dmSecCb.bdAddr;
|
||||
} else {
|
||||
return HciGetBdAddr();
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief For internal use only. This function gets the local identity address type used by the
|
||||
* device.
|
||||
*
|
||||
* \return The identity address type.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
uint8_t DmSecGetLocalIdentityAddrType(void)
|
||||
{
|
||||
if (dmSecCb.addrType != DM_ADDR_NONE) {
|
||||
return dmSecCb.addrType;
|
||||
} else {
|
||||
return DM_ADDR_PUBLIC;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************************************/
|
||||
/*!
|
||||
* \brief Reset the sec module.
|
||||
|
|
|
@ -83,6 +83,8 @@ typedef struct
|
|||
{
|
||||
uint8_t *pIrk;
|
||||
uint8_t *pCsrk;
|
||||
bdAddr_t bdAddr;
|
||||
uint8_t addrType;
|
||||
} dmSecCb_t;
|
||||
|
||||
/**************************************************************************************************
|
||||
|
|
|
@ -567,8 +567,8 @@ bool_t smpSendKey(smpCcb_t *pCcb, uint8_t keyDist)
|
|||
{
|
||||
/* send second part of IRK */
|
||||
UINT8_TO_BSTREAM(p, SMP_CMD_ID_ADDR_INFO);
|
||||
UINT8_TO_BSTREAM(p, DM_ADDR_PUBLIC);
|
||||
BDA_TO_BSTREAM(p, HciGetBdAddr());
|
||||
UINT8_TO_BSTREAM(p, DmSecGetLocalIdentityAddrType());
|
||||
BDA_TO_BSTREAM(p, DmSecGetLocalIdentityAddr());
|
||||
|
||||
}
|
||||
else if ((keyDist & SMP_KEY_DIST_SIGN) &&
|
||||
|
|
|
@ -92,6 +92,29 @@
|
|||
"help": "How many advertising sets the API can handle (this limits how much the stack can handle). Must be non-zero",
|
||||
"value": 15,
|
||||
"macro_name": "BLE_GAP_MAX_ADVERTISING_SETS"
|
||||
},
|
||||
"ble-gap-host-based-private-address-resolution": {
|
||||
"help": "Perform address resolution on the host, not the controller. Controller based privacy is preferred as it happens lower down the stack but this can be used in case controller based privacy is unavailable. If this is enabled the controller will not be used for privacy.",
|
||||
"value": true,
|
||||
"macro_name": "BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION"
|
||||
},
|
||||
"ble-gap-max-advertising-reports-pending-address-resolution": {
|
||||
"help": "How many advertising reports can be pending while awaiting private address resolution. This is only used if host privacy is enabled and controller privacy is disabled. Must be non-zero",
|
||||
"value": 16,
|
||||
"macro_name": "BLE_GAP_MAX_ADVERTISING_REPORTS_PENDING_ADDRESS_RESOLUTION"
|
||||
},
|
||||
"ble-gap-host-privacy-resolved-cache-size": {
|
||||
"help": "Used for host privacy. How many last resolved addresses to store to speed up resolution. This is especially valuable for resolving advertising which creates repeated queries for the same address.",
|
||||
"value": 16,
|
||||
"macro_name": "BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE"
|
||||
}
|
||||
},
|
||||
"target_overrides": {
|
||||
"MCU_NRF52840": {
|
||||
"ble-gap-host-based-private-address-resolution": false
|
||||
},
|
||||
"NUCLEO_WB55RG": {
|
||||
"ble-gap-host-based-private-address-resolution": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -501,4 +501,9 @@ ble_error_t Gap::setRandomStaticAddress(const ble::address_t &address)
|
|||
return impl->setRandomStaticAddress(address);
|
||||
}
|
||||
|
||||
ble::address_t Gap::getRandomStaticAddress()
|
||||
{
|
||||
return impl->getRandomStaticAddress();
|
||||
}
|
||||
|
||||
} // namespace ble
|
|
@ -192,12 +192,14 @@ ble_error_t SecurityManager::getSigningKey(ble::connection_handle_t connectionHa
|
|||
return impl->getSigningKey(connectionHandle, authenticated);
|
||||
}
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t SecurityManager::setPrivateAddressTimeout(
|
||||
uint16_t timeout_in_seconds
|
||||
)
|
||||
{
|
||||
return impl->setPrivateAddressTimeout(timeout_in_seconds);
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
void SecurityManager::onShutdown(const SecurityManagerShutdownCallback_t& callback)
|
||||
{
|
||||
|
|
|
@ -200,8 +200,10 @@ ble::impl::Gap &BLEInstanceBase::getGapImpl()
|
|||
static ble::impl::Gap gap(
|
||||
_event_queue,
|
||||
ble::impl::PalGap::get_gap(),
|
||||
cordio_gap_service,
|
||||
ble::impl::PalSecurityManager::get_security_manager()
|
||||
cordio_gap_service
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
, getPrivateAddressRegistry()
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
);
|
||||
return gap;
|
||||
}
|
||||
|
@ -220,7 +222,6 @@ const ble::Gap &BLEInstanceBase::getGap() const
|
|||
};
|
||||
|
||||
#if BLE_FEATURE_GATT_SERVER
|
||||
|
||||
ble::impl::GattServer &BLEInstanceBase::getGattServerImpl()
|
||||
{
|
||||
return ble::impl::GattServer::getInstance();
|
||||
|
@ -238,11 +239,9 @@ const ble::GattServer &BLEInstanceBase::getGattServer() const
|
|||
auto &self = const_cast<BLEInstanceBase &>(*this);
|
||||
return const_cast<const ble::GattServer &>(self.getGattServer());
|
||||
}
|
||||
|
||||
#endif // BLE_FEATURE_GATT_SERVER
|
||||
|
||||
#if BLE_FEATURE_GATT_CLIENT
|
||||
|
||||
ble::impl::GattClient &BLEInstanceBase::getGattClientImpl()
|
||||
{
|
||||
static ble::impl::GattClient gatt_client(getPalGattClient());
|
||||
|
@ -261,11 +260,9 @@ PalGattClient &BLEInstanceBase::getPalGattClient()
|
|||
static PalAttClientToGattClient pal_gatt_client(impl::PalAttClient::get_client());
|
||||
return pal_gatt_client;
|
||||
}
|
||||
|
||||
#endif // BLE_FEATURE_GATT_CLIENT
|
||||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
|
||||
ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl()
|
||||
{
|
||||
// Creation of a proxy monitor to let the security manager register to
|
||||
|
@ -286,11 +283,15 @@ ble::impl::SecurityManager &BLEInstanceBase::getSecurityManagerImpl()
|
|||
ble::impl::PalSecurityManager::get_security_manager(),
|
||||
getGapImpl(),
|
||||
signing_event_monitor
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
, getPrivateAddressRegistry()
|
||||
#endif //BLE_FEATURE_PRIVACY
|
||||
);
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
ble::SecurityManager &BLEInstanceBase::getSecurityManager()
|
||||
{
|
||||
static ble::SecurityManager m_instance(&getSecurityManagerImpl());
|
||||
|
@ -302,7 +303,19 @@ const ble::SecurityManager &BLEInstanceBase::getSecurityManager() const
|
|||
const BLEInstanceBase &self = const_cast<BLEInstanceBase &>(*this);
|
||||
return const_cast<const ble::SecurityManager &>(self.getSecurityManager());
|
||||
}
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble::PrivateAddressController &BLEInstanceBase::getPrivateAddressRegistry()
|
||||
{
|
||||
static ble::PrivateAddressController registry(
|
||||
impl::PalPrivateAddressController::instance(),
|
||||
_event_queue,
|
||||
ble::resolvable_address_timeout_t{}
|
||||
);
|
||||
return registry;
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
||||
void BLEInstanceBase::waitForEvent()
|
||||
|
@ -337,6 +350,12 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
|||
if (ble::impl::PalSecurityManager::get_security_manager().sm_handler(msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
if (impl::PalPrivateAddressController::instance().cordio_handler(msg)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
||||
switch (msg->event) {
|
||||
|
@ -365,6 +384,7 @@ void BLEInstanceBase::stack_handler(wsfEventMask_t event, wsfMsgHdr_t *msg)
|
|||
#if BLE_FEATURE_GATT_SERVER
|
||||
deviceInstance().getGattServerImpl().initialize();
|
||||
#endif
|
||||
|
||||
deviceInstance().initialization_status = INITIALIZED;
|
||||
_init_callback.call(&context);
|
||||
} break;
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
#include "source/generic/SecurityManagerImpl.h"
|
||||
#include "source/GattServerImpl.h"
|
||||
#include "source/PalEventQueueImpl.h"
|
||||
#include "source/PalPrivateAddressControllerImpl.h"
|
||||
#include "source/generic/PrivateAddressController.h"
|
||||
|
||||
#include "drivers/LowPowerTimer.h"
|
||||
|
||||
|
@ -157,6 +159,10 @@ public:
|
|||
*/
|
||||
const ble::SecurityManager &getSecurityManager() const final;
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble::PrivateAddressController &getPrivateAddressRegistry();
|
||||
#endif
|
||||
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
||||
/**
|
||||
|
|
|
@ -116,11 +116,13 @@ public:
|
|||
void process()
|
||||
{
|
||||
while (_events) {
|
||||
EventNode *next = _events->next;
|
||||
_events->event();
|
||||
_events->~EventNode();
|
||||
WsfBufFree(_events);
|
||||
_events = next;
|
||||
// pop
|
||||
auto *event = _events;
|
||||
_events = event->next;
|
||||
// execute and delete
|
||||
event->event();
|
||||
event->~EventNode();
|
||||
WsfBufFree(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
#include "source/PalGapImpl.h"
|
||||
#include "ble/common/BLERoles.h"
|
||||
#include "hci_api.h"
|
||||
#include "dm_api.h"
|
||||
#include "dm_main.h"
|
||||
|
@ -462,23 +463,6 @@ ble_error_t PalGap::disconnect(
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
bool PalGap::is_privacy_supported()
|
||||
{
|
||||
// We only support controller-based privacy, so return whether the controller supports it
|
||||
return HciLlPrivacySupported();
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalGap::set_address_resolution(
|
||||
bool enable
|
||||
)
|
||||
{
|
||||
DmPrivSetAddrResEnable(enable);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalGap::read_phy(connection_handle_t connection)
|
||||
{
|
||||
if (is_feature_supported(controller_supported_features_t::LE_2M_PHY)
|
||||
|
@ -489,7 +473,6 @@ ble_error_t PalGap::read_phy(connection_handle_t connection)
|
|||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalGap::set_preferred_phys(
|
||||
const phy_set_t &tx_phys,
|
||||
const phy_set_t &rx_phys
|
||||
|
@ -589,7 +572,9 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
break;
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
#if BLE_ROLE_OBSERVER
|
||||
case DM_PER_ADV_SYNC_EST_IND: {
|
||||
if (!handler) {
|
||||
break;
|
||||
|
@ -637,8 +622,25 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
handler->on_periodic_advertising_sync_loss(evt->syncHandle);
|
||||
}
|
||||
break;
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#endif // BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
case DM_ADV_START_IND:
|
||||
if (!handler) {
|
||||
break;
|
||||
}
|
||||
handler->on_legacy_advertising_started();
|
||||
break;
|
||||
|
||||
case DM_ADV_STOP_IND:
|
||||
if (!handler) {
|
||||
break;
|
||||
}
|
||||
handler->on_legacy_advertising_stopped();
|
||||
break;
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER
|
||||
case DM_SCAN_REQ_RCVD_IND: {
|
||||
if (!handler) {
|
||||
|
@ -651,8 +653,16 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
connection_peer_address_type_t(evt->scanAddrType),
|
||||
evt->scanAddr
|
||||
);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case DM_ADV_SET_START_IND: {
|
||||
if (!handler) {
|
||||
break;
|
||||
}
|
||||
const auto *evt = (const dmAdvSetStartEvt_t *) msg;
|
||||
handler->on_advertising_set_started({evt->advHandle, evt->numSets});
|
||||
} break;
|
||||
|
||||
|
||||
case DM_ADV_SET_STOP_IND: {
|
||||
const auto *evt = (const hciLeAdvSetTermEvt_t *) msg;
|
||||
|
@ -676,20 +686,40 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
evt->handle,
|
||||
evt->numComplEvts
|
||||
);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_OBSERVER
|
||||
#if BLE_ROLE_OBSERVER
|
||||
case DM_SCAN_START_IND:
|
||||
if (!handler) { break; }
|
||||
handler->on_scan_started(msg->status == HCI_SUCCESS);
|
||||
break;
|
||||
|
||||
case DM_SCAN_STOP_IND:
|
||||
if (!handler) { break; }
|
||||
handler->on_scan_stopped(msg->status == HCI_SUCCESS);
|
||||
break;
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
case DM_EXT_SCAN_START_IND:
|
||||
if (!handler) { break; }
|
||||
handler->on_scan_started(msg->status == HCI_SUCCESS);
|
||||
break;
|
||||
|
||||
case DM_EXT_SCAN_STOP_IND: {
|
||||
if (!handler) {
|
||||
get_gap().ext_scan_stopping = false;
|
||||
break;
|
||||
}
|
||||
|
||||
//const hciLeScanTimeoutEvt_t *evt = (const hciLeScanTimeoutEvt_t *) msg;
|
||||
handler->on_scan_timeout();
|
||||
}
|
||||
break;
|
||||
if (get_gap().ext_scan_stopping) {
|
||||
get_gap().ext_scan_stopping = false;
|
||||
handler->on_scan_stopped(msg->status == HCI_SUCCESS);
|
||||
} else {
|
||||
handler->on_scan_timeout();
|
||||
}
|
||||
|
||||
} break;
|
||||
|
||||
case DM_EXT_SCAN_REPORT_IND: {
|
||||
if (!handler) {
|
||||
|
@ -715,11 +745,11 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
evt->len,
|
||||
evt->pData
|
||||
);
|
||||
}
|
||||
break;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING && BLE_ROLE_OBSERVER
|
||||
} break;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
case DM_REM_CONN_PARAM_REQ_IND: {
|
||||
if (!handler) {
|
||||
break;
|
||||
|
@ -745,7 +775,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
get_gap().get_running_conn_direct_adv_cb(evt->hdr.param);
|
||||
if (adv_cb) {
|
||||
adv_cb->state = direct_adv_cb_t::free;
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
if (handler) {
|
||||
handler->on_advertising_set_terminated(
|
||||
hci_error_code_t(evt->status),
|
||||
|
@ -754,6 +784,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
0
|
||||
);
|
||||
}
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -770,7 +801,7 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
}
|
||||
}
|
||||
break;
|
||||
#endif // BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
}
|
||||
|
||||
// all handlers are stored in a static array
|
||||
|
@ -778,12 +809,12 @@ void PalGap::gap_handler(const wsfMsgHdr_t *msg)
|
|||
#if BLE_ROLE_OBSERVER
|
||||
&event_handler<GapAdvertisingReportMessageConverter>,
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#if BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
&event_handler<ConnectionCompleteMessageConverter>,
|
||||
&event_handler<DisconnectionMessageConverter>,
|
||||
&event_handler<ConnectionUpdateMessageConverter>,
|
||||
&event_handler<RemoteConnectionParameterRequestMessageConverter>,
|
||||
#endif // BLE_ROLE_CENTRAL || BLE_ROLE_PERIPHERAL
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
&dummy_gap_event_handler
|
||||
};
|
||||
|
||||
|
@ -822,7 +853,7 @@ ble_error_t PalGap::set_advertising_set_random_address(
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
ble_error_t PalGap::set_extended_advertising_parameters(
|
||||
advertising_handle_t advertising_handle,
|
||||
advertising_event_properties_t event_properties,
|
||||
|
@ -962,7 +993,7 @@ ble_error_t PalGap::set_extended_advertising_parameters(
|
|||
peer_address_type
|
||||
);
|
||||
}
|
||||
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
ble_error_t PalGap::set_periodic_advertising_parameters(
|
||||
advertising_handle_t advertising_handle,
|
||||
|
@ -1240,6 +1271,7 @@ ble_error_t PalGap::extended_scan_enable(
|
|||
if (enable) {
|
||||
uint32_t duration_ms = duration * 10;
|
||||
|
||||
|
||||
DmScanStart(
|
||||
scanning_phys.value(),
|
||||
DM_DISC_MODE_NONE,
|
||||
|
@ -1250,6 +1282,7 @@ ble_error_t PalGap::extended_scan_enable(
|
|||
);
|
||||
} else {
|
||||
DmScanStop();
|
||||
ext_scan_stopping = true;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
|
|
|
@ -147,12 +147,6 @@ public:
|
|||
local_disconnection_reason_t disconnection_reason
|
||||
) final;
|
||||
|
||||
bool is_privacy_supported() final;
|
||||
|
||||
ble_error_t set_address_resolution(
|
||||
bool enable
|
||||
) final;
|
||||
|
||||
ble_error_t read_phy(connection_handle_t connection) final;
|
||||
|
||||
ble_error_t set_preferred_phys(
|
||||
|
@ -180,6 +174,7 @@ public:
|
|||
const address_t &address
|
||||
) final;
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
ble_error_t set_extended_advertising_parameters(
|
||||
advertising_handle_t advertising_handle,
|
||||
advertising_event_properties_t event_properties,
|
||||
|
@ -197,6 +192,7 @@ public:
|
|||
uint8_t advertising_sid,
|
||||
bool scan_request_notification
|
||||
) final;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
ble_error_t set_periodic_advertising_parameters(
|
||||
advertising_handle_t advertising_handle,
|
||||
|
@ -370,18 +366,30 @@ private:
|
|||
|
||||
static GapConnectionCompleteEvent convert(const hciLeConnCmplEvt_t *conn_evt)
|
||||
{
|
||||
const bdAddr_t *peer_rpa = &conn_evt->peerRpa;
|
||||
const bdAddr_t *peer_address = &conn_evt->peerAddr;
|
||||
|
||||
#if defined(TARGET_MCU_STM32WB55xx)
|
||||
const bdAddr_t invalidAddress = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (conn_evt->addrType == DM_ADDR_RANDOM &&
|
||||
memcmp(peer_address, invalidAddress, sizeof(invalidAddress)) == 0 &&
|
||||
memcmp(peer_rpa, invalidAddress, sizeof(invalidAddress) != 0)
|
||||
) {
|
||||
std::swap(peer_rpa, peer_address);
|
||||
}
|
||||
#endif
|
||||
return GapConnectionCompleteEvent(
|
||||
conn_evt->status,
|
||||
// note the usage of the stack handle, not the HCI handle
|
||||
conn_evt->hdr.param,
|
||||
(connection_role_t::type) conn_evt->role,
|
||||
(peer_address_type_t::type) conn_evt->addrType,
|
||||
conn_evt->peerAddr,
|
||||
*peer_address,
|
||||
conn_evt->connInterval,
|
||||
conn_evt->connLatency,
|
||||
conn_evt->supTimeout,
|
||||
conn_evt->localRpa,
|
||||
conn_evt->peerRpa
|
||||
*peer_rpa
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -541,6 +549,7 @@ private:
|
|||
uint8_t extended_scan_type[3];
|
||||
phy_set_t scanning_phys;
|
||||
direct_adv_cb_t direct_adv_cb[DM_NUM_ADV_SETS];
|
||||
bool ext_scan_stopping = false;
|
||||
|
||||
/**
|
||||
* Callback called when an event is emitted by the LE subsystem.
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include "PalPrivateAddressControllerImpl.h"
|
||||
#include "dm_api.h"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
ble_error_t PalPrivateAddressController::initialize()
|
||||
{
|
||||
DmPrivInit();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::terminate()
|
||||
{
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::generate_resolvable_private_address(const irk_t& local_irk)
|
||||
{
|
||||
if (_generating_rpa) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
DmPrivGenerateAddr(const_cast<uint8_t*>(local_irk.data()), 0);
|
||||
_generating_rpa = true;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
address_t PalPrivateAddressController::generate_non_resolvable_private_address()
|
||||
{
|
||||
address_t address;
|
||||
SecRand(address.data(), address.size());
|
||||
DM_RAND_ADDR_SET(address, DM_RAND_ADDR_NONRESOLV);
|
||||
return address;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::resolve_private_address(
|
||||
const address_t &address,
|
||||
const irk_t& irk
|
||||
)
|
||||
{
|
||||
if (_resolving_rpa) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
DmPrivResolveAddr(
|
||||
const_cast<uint8_t*>(address.data()),
|
||||
const_cast<uint8_t*>(irk.data()),
|
||||
0
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool PalPrivateAddressController::is_ll_privacy_supported()
|
||||
{
|
||||
return HciLlPrivacySupported();
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::set_ll_address_resolution(bool enable)
|
||||
{
|
||||
DmPrivSetAddrResEnable(enable);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::set_ll_resolvable_private_address_timeout(
|
||||
resolvable_address_timeout_t timeout
|
||||
)
|
||||
{
|
||||
if (HciLlPrivacySupported() == false) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
DmPrivSetResolvablePrivateAddrTimeout(timeout.value());
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint8_t PalPrivateAddressController::read_resolving_list_capacity()
|
||||
{
|
||||
return HciGetResolvingListSize();
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::add_device_to_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t& peer_irk,
|
||||
const irk_t& local_irk
|
||||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
DmPrivAddDevToResList(
|
||||
peer_address_type.value(),
|
||||
peer_identity_address.data(),
|
||||
const_cast<uint8_t*>(peer_irk.data()),
|
||||
const_cast<uint8_t*>(local_irk.data()),
|
||||
false,
|
||||
0
|
||||
);
|
||||
DmPrivSetPrivacyMode(
|
||||
peer_address_type.value(),
|
||||
peer_identity_address.data(),
|
||||
DM_PRIV_MODE_DEVICE
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::remove_device_from_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
DmPrivRemDevFromResList(peer_address_type.value(), peer_identity_address.data(), 0);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::set_peer_privacy_mode(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address,
|
||||
privacy_mode_t privacy_mode
|
||||
)
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
DmPrivSetPrivacyMode(
|
||||
peer_address_type.value(),
|
||||
peer_address.data(),
|
||||
privacy_mode.value()
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalPrivateAddressController::clear_resolving_list()
|
||||
{
|
||||
if (is_ll_privacy_supported() == false) {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
DmPrivClearResList();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void PalPrivateAddressController::set_event_handler(EventHandler *handler)
|
||||
{
|
||||
_event_handler = handler;
|
||||
}
|
||||
|
||||
PalPrivateAddressController& PalPrivateAddressController::instance()
|
||||
{
|
||||
static impl::PalPrivateAddressController self;
|
||||
return self;
|
||||
}
|
||||
|
||||
bool PalPrivateAddressController::cordio_handler(const wsfMsgHdr_t *msg)
|
||||
{
|
||||
if (msg == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* handler = instance()._event_handler;
|
||||
|
||||
switch (msg->event) {
|
||||
case DM_PRIV_GENERATE_ADDR_IND: {
|
||||
instance()._generating_rpa = false;
|
||||
|
||||
if (!handler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto *evt = (const dmPrivGenAddrIndEvt_t*) msg;
|
||||
if (evt->hdr.status == HCI_SUCCESS) {
|
||||
handler->on_resolvable_private_address_generated(evt->addr);
|
||||
} else {
|
||||
handler->on_resolvable_private_address_generated(address_t{});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
case DM_PRIV_RESOLVED_ADDR_IND: {
|
||||
instance()._resolving_rpa = false;
|
||||
|
||||
if (!handler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
handler->on_private_address_resolved(msg->status == HCI_SUCCESS);
|
||||
return true;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
case DM_PRIV_ADD_DEV_TO_RES_LIST_IND: // Device added to resolving list
|
||||
case DM_PRIV_REM_DEV_FROM_RES_LIST_IND: // Device removed from resolving list
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND: // Resolving list cleared
|
||||
{
|
||||
if (!handler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Previous command completed, we can move to the next control block
|
||||
handler->on_resolving_list_action_complete();
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
} // namespace ble
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
|
@ -0,0 +1,98 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H
|
||||
#define BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include "source/pal/PalPrivateAddressController.h"
|
||||
#include "dm_api.h"
|
||||
|
||||
namespace ble {
|
||||
namespace impl {
|
||||
|
||||
/**
|
||||
* Cordio implementation of a ble::PalPrivateAddressController.
|
||||
*/
|
||||
struct PalPrivateAddressController final : public ble::PalPrivateAddressController {
|
||||
|
||||
ble_error_t initialize() final;
|
||||
|
||||
ble_error_t terminate() final;
|
||||
|
||||
ble_error_t generate_resolvable_private_address(const irk_t& local_irk) final;
|
||||
|
||||
address_t generate_non_resolvable_private_address() final;
|
||||
|
||||
ble_error_t resolve_private_address(
|
||||
const address_t &address,
|
||||
const irk_t& irk
|
||||
) final;
|
||||
|
||||
bool is_ll_privacy_supported() final;
|
||||
|
||||
ble_error_t set_ll_address_resolution(bool enable) final;
|
||||
|
||||
ble_error_t set_ll_resolvable_private_address_timeout(resolvable_address_timeout_t timeout) final;
|
||||
|
||||
uint8_t read_resolving_list_capacity() final;
|
||||
|
||||
ble_error_t add_device_to_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t& peer_irk,
|
||||
const irk_t& local_irk
|
||||
) final;
|
||||
|
||||
ble_error_t remove_device_from_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) final;
|
||||
|
||||
ble_error_t clear_resolving_list() final;
|
||||
|
||||
ble_error_t set_peer_privacy_mode(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address,
|
||||
privacy_mode_t privacy_mode
|
||||
) final;
|
||||
|
||||
void set_event_handler(EventHandler *handler) final;
|
||||
|
||||
static PalPrivateAddressController& instance();
|
||||
|
||||
/**
|
||||
* Callback which handle wsfMsgHdr_t and forward them to emit_gap_event.
|
||||
*/
|
||||
static bool cordio_handler(const wsfMsgHdr_t *msg);
|
||||
|
||||
private:
|
||||
PalPrivateAddressController() = default;
|
||||
|
||||
EventHandler *_event_handler = nullptr;
|
||||
bool _generating_rpa = false;
|
||||
bool _resolving_rpa = false;
|
||||
};
|
||||
|
||||
|
||||
} // namespace impl
|
||||
} // namespace ble
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#endif //BLE_CORDIO_PAL_PRIVATE_ADDRESS_CONTROLLER_IMPL_H
|
|
@ -16,6 +16,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "ble/common/BLERoles.h"
|
||||
|
@ -37,17 +39,12 @@ PalSecurityManager::PalSecurityManager() :
|
|||
_default_passkey(0),
|
||||
_lesc_keys_generated(false),
|
||||
_public_key_x(),
|
||||
_pending_privacy_control_blocks(nullptr),
|
||||
_processing_privacy_control_block(false),
|
||||
_peer_csrks()
|
||||
{
|
||||
}
|
||||
|
||||
PalSecurityManager::~PalSecurityManager()
|
||||
{
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
clear_privacy_control_blocks();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -93,68 +90,6 @@ ble_error_t PalSecurityManager::reset()
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Resolving list management
|
||||
//
|
||||
|
||||
|
||||
uint8_t PalSecurityManager::read_resolving_list_capacity()
|
||||
{
|
||||
// The Cordio stack requests this from the controller during initialization
|
||||
return hciCoreCb.resListSize;
|
||||
}
|
||||
|
||||
// As the Cordio stack can only handle one of these methods at a time, we need to create a list of control blocks
|
||||
// that are dequeued one after the other on completion of the previous one
|
||||
|
||||
ble_error_t PalSecurityManager::add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
)
|
||||
{
|
||||
if (read_resolving_list_capacity() == 0) {
|
||||
// If 0 is returned as capacity, it means the controller does not support resolving addresses
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Queue control block
|
||||
queue_add_device_to_resolving_list(peer_identity_address_type, peer_identity_address, peer_irk);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalSecurityManager::remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
if (read_resolving_list_capacity() == 0) {
|
||||
// If 0 is returned as capacity, it means the controller does not support resolving addresses
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Queue control block
|
||||
queue_remove_device_from_resolving_list(peer_identity_address_type, peer_identity_address);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t PalSecurityManager::clear_resolving_list()
|
||||
{
|
||||
if (read_resolving_list_capacity() == 0) {
|
||||
// If 0 is returned as capacity, it means the controller does not support resolving addresses
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Queue control block
|
||||
queue_clear_resolving_list();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Feature support
|
||||
//
|
||||
|
@ -274,33 +209,6 @@ ble_error_t PalSecurityManager::encrypt_data(
|
|||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Privacy
|
||||
//
|
||||
|
||||
|
||||
ble_error_t PalSecurityManager::set_private_address_timeout(
|
||||
uint16_t timeout_in_seconds
|
||||
)
|
||||
{
|
||||
DmPrivSetResolvablePrivateAddrTimeout(timeout_in_seconds);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::get_identity_address
|
||||
*/
|
||||
|
||||
ble_error_t PalSecurityManager::get_identity_address(
|
||||
address_t &address,
|
||||
bool &public_address
|
||||
)
|
||||
{
|
||||
// On cordio, the public address is hardcoded as the identity address.
|
||||
address = address_t(HciGetBdAddr());
|
||||
public_address = true;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
|
@ -355,6 +263,17 @@ ble_error_t PalSecurityManager::set_irk(const irk_t &irk)
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalSecurityManager::set_identity_address(
|
||||
const address_t &address,
|
||||
bool public_address
|
||||
)
|
||||
{
|
||||
DmSecSetLocalIdentityAddr(
|
||||
address.data(),
|
||||
public_address ? DM_ADDR_PUBLIC : DM_ADDR_RANDOM
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t PalSecurityManager::set_csrk(
|
||||
const csrk_t &csrk,
|
||||
|
@ -841,220 +760,13 @@ bool PalSecurityManager::sm_handler(const wsfMsgHdr_t *msg)
|
|||
return true;
|
||||
}
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
// Privacy
|
||||
case DM_PRIV_ADD_DEV_TO_RES_LIST_IND: // Device added to resolving list
|
||||
case DM_PRIV_REM_DEV_FROM_RES_LIST_IND: // Device removed from resolving list
|
||||
case DM_PRIV_CLEAR_RES_LIST_IND: // Resolving list cleared
|
||||
{
|
||||
// Previous command completed, we can move to the next control block
|
||||
self.process_privacy_control_blocks(true);
|
||||
return true;
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct PalSecurityManager::PrivacyControlBlock {
|
||||
PrivacyControlBlock() : _next(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PrivacyControlBlock() = default;
|
||||
|
||||
virtual void execute() = 0;
|
||||
|
||||
void set_next(PrivacyControlBlock *next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
PrivacyControlBlock *next() const
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
PrivacyControlBlock *_next;
|
||||
};
|
||||
|
||||
|
||||
struct PalSecurityManager::PrivacyClearResListControlBlock final : PalSecurityManager::PrivacyControlBlock {
|
||||
PrivacyClearResListControlBlock() : PrivacyControlBlock()
|
||||
{
|
||||
}
|
||||
|
||||
void execute() final
|
||||
{
|
||||
// Execute command
|
||||
DmPrivClearResList();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct PalSecurityManager::PrivacyAddDevToResListControlBlock final : PalSecurityManager::PrivacyControlBlock {
|
||||
PrivacyAddDevToResListControlBlock(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
) : PrivacyControlBlock(),
|
||||
_peer_identity_address_type(peer_identity_address_type),
|
||||
_peer_identity_address(peer_identity_address),
|
||||
_peer_irk(peer_irk)
|
||||
{
|
||||
}
|
||||
|
||||
void execute() final
|
||||
{
|
||||
// Execute command
|
||||
DmPrivAddDevToResList(
|
||||
_peer_identity_address_type.value(),
|
||||
_peer_identity_address.data(),
|
||||
_peer_irk.data(),
|
||||
DmSecGetLocalIrk(),
|
||||
false,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_peer_address_type_t _peer_identity_address_type;
|
||||
address_t _peer_identity_address;
|
||||
irk_t _peer_irk;
|
||||
};
|
||||
|
||||
|
||||
struct PalSecurityManager::PrivacyRemoveDevFromResListControlBlock final : PalSecurityManager::PrivacyControlBlock {
|
||||
PrivacyRemoveDevFromResListControlBlock(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) : PrivacyControlBlock(),
|
||||
_peer_identity_address_type(peer_identity_address_type),
|
||||
_peer_identity_address(peer_identity_address)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void execute() final
|
||||
{
|
||||
// Execute command
|
||||
DmPrivRemDevFromResList(_peer_identity_address_type.value(), _peer_identity_address.data(), 0);
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_peer_address_type_t _peer_identity_address_type;
|
||||
address_t _peer_identity_address;
|
||||
};
|
||||
|
||||
// Helper functions for privacy
|
||||
|
||||
void PalSecurityManager::queue_add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
)
|
||||
{
|
||||
auto *cb = new(std::nothrow) PrivacyAddDevToResListControlBlock(
|
||||
peer_identity_address_type,
|
||||
peer_identity_address,
|
||||
peer_irk
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
}
|
||||
|
||||
|
||||
void PalSecurityManager::queue_remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
auto *cb = new(std::nothrow) PrivacyRemoveDevFromResListControlBlock(
|
||||
peer_identity_address_type,
|
||||
peer_identity_address
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
}
|
||||
|
||||
|
||||
void PalSecurityManager::queue_clear_resolving_list()
|
||||
{
|
||||
// Remove any pending control blocks, there's no point executing them as we're about to queue the list
|
||||
clear_privacy_control_blocks();
|
||||
|
||||
auto *cb = new(std::nothrow) PrivacyClearResListControlBlock();
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
}
|
||||
|
||||
|
||||
void PalSecurityManager::clear_privacy_control_blocks()
|
||||
{
|
||||
while (_pending_privacy_control_blocks != nullptr) {
|
||||
PrivacyControlBlock *next = _pending_privacy_control_blocks->next();
|
||||
delete _pending_privacy_control_blocks;
|
||||
_pending_privacy_control_blocks = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PalSecurityManager::queue_privacy_control_block(PrivacyControlBlock *block)
|
||||
{
|
||||
if (_pending_privacy_control_blocks == nullptr) {
|
||||
_pending_privacy_control_blocks = block;
|
||||
} else {
|
||||
PrivacyControlBlock *node = _pending_privacy_control_blocks;
|
||||
while (node->next() != nullptr) {
|
||||
node = node->next();
|
||||
}
|
||||
node->set_next(block);
|
||||
}
|
||||
|
||||
process_privacy_control_blocks(false);
|
||||
}
|
||||
|
||||
// If cb_completed is set to true, it means the previous control block has completed
|
||||
|
||||
void PalSecurityManager::process_privacy_control_blocks(bool cb_completed)
|
||||
{
|
||||
if ((_processing_privacy_control_block == true) && !cb_completed) {
|
||||
// Busy, cannot process next control block for now
|
||||
return;
|
||||
}
|
||||
|
||||
PrivacyControlBlock *cb = _pending_privacy_control_blocks;
|
||||
if (cb == nullptr) {
|
||||
// All control blocks processed
|
||||
_processing_privacy_control_block = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Process next block and free it
|
||||
_processing_privacy_control_block = true;
|
||||
|
||||
PrivacyControlBlock *next = cb->next();
|
||||
cb->execute();
|
||||
delete cb;
|
||||
_pending_privacy_control_blocks = next;
|
||||
}
|
||||
|
||||
|
||||
void PalSecurityManager::cleanup_peer_csrks()
|
||||
{
|
||||
for (auto & peer_csrk : _peer_csrks) {
|
||||
|
@ -1079,3 +791,5 @@ PalSecurityManagerEventHandler *PalSecurityManager::get_event_handler()
|
|||
|
||||
} // namespace impl
|
||||
} // namespace ble
|
||||
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
|
|
@ -59,37 +59,6 @@ public:
|
|||
*/
|
||||
ble_error_t reset() final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Resolving list management
|
||||
//
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::read_resolving_list_capacity
|
||||
*/
|
||||
uint8_t read_resolving_list_capacity() final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::add_device_to_resolving_list
|
||||
*/
|
||||
ble_error_t add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
) final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::remove_device_from_resolving_list
|
||||
*/
|
||||
ble_error_t remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::clear_resolving_list
|
||||
*/
|
||||
ble_error_t clear_resolving_list() final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pairing
|
||||
//
|
||||
|
@ -205,20 +174,6 @@ public:
|
|||
encryption_block_t &data
|
||||
) final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Privacy
|
||||
//
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::set_private_address_timeout
|
||||
*/
|
||||
ble_error_t set_private_address_timeout(uint16_t timeout_in_seconds) final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::get_identity_address
|
||||
*/
|
||||
ble_error_t get_identity_address(address_t &address, bool &public_address) final;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
//
|
||||
|
@ -245,6 +200,13 @@ public:
|
|||
*/
|
||||
ble_error_t set_irk(const irk_t &irk) final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::set_identity_address
|
||||
*/
|
||||
ble_error_t set_identity_address(
|
||||
const address_t &address, bool public_address
|
||||
) final;
|
||||
|
||||
/**
|
||||
* @see ::ble::PalSecurityManager::set_csrk
|
||||
*/
|
||||
|
@ -347,37 +309,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
struct PrivacyControlBlock;
|
||||
struct PrivacyClearResListControlBlock;
|
||||
struct PrivacyAddDevToResListControlBlock;
|
||||
struct PrivacyRemoveDevFromResListControlBlock;
|
||||
|
||||
// Queue control block to add device to resolving list
|
||||
void queue_add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
);
|
||||
|
||||
// Queue control block to remove device from resolving list
|
||||
void queue_remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
);
|
||||
|
||||
// Queue control block to clear resolving list
|
||||
void queue_clear_resolving_list();
|
||||
|
||||
// Clear all control blocks
|
||||
void clear_privacy_control_blocks();
|
||||
|
||||
// Queue a control block
|
||||
void queue_privacy_control_block(PrivacyControlBlock *block);
|
||||
|
||||
// Try to dequeue and process the next control block
|
||||
// cb_completed is set when the previous block has completed
|
||||
void process_privacy_control_blocks(bool cb_completed);
|
||||
|
||||
void cleanup_peer_csrks();
|
||||
|
||||
PalSecurityManagerEventHandler *_pal_event_handler;
|
||||
|
@ -386,9 +317,6 @@ private:
|
|||
passkey_num_t _default_passkey;
|
||||
bool _lesc_keys_generated;
|
||||
uint8_t _public_key_x[SEC_ECC_KEY_LEN];
|
||||
|
||||
PrivacyControlBlock *_pending_privacy_control_blocks;
|
||||
bool _processing_privacy_control_block;
|
||||
irk_t _irk;
|
||||
csrk_t _csrk;
|
||||
csrk_t *_peer_csrks[DM_CONN_MAX];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "source/pal/PalGap.h"
|
||||
#include "source/pal/PalConnectionMonitor.h"
|
||||
#include "source/pal/PalEventQueue.h"
|
||||
#include "source/generic/PrivateAddressController.h"
|
||||
|
||||
#include "ble/Gap.h"
|
||||
|
||||
|
@ -57,7 +59,11 @@ class BLEInstanceBase;
|
|||
|
||||
class Gap :
|
||||
public ble::PalConnectionMonitor,
|
||||
public PalGapEventHandler {
|
||||
public PalGapEventHandler
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
, public PrivateAddressController::EventHandler
|
||||
#endif //BLE_FEATURE_PRIVACY
|
||||
{
|
||||
friend PalConnectionMonitor;
|
||||
friend PalGapEventHandler;
|
||||
friend PalGap;
|
||||
|
@ -69,17 +75,23 @@ class Gap :
|
|||
public:
|
||||
using PreferredConnectionParams_t = ::ble::Gap::PreferredConnectionParams_t ;
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
/**
|
||||
* Default peripheral privacy configuration.
|
||||
*/
|
||||
static const peripheral_privacy_configuration_t
|
||||
default_peripheral_privacy_configuration;
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
/**
|
||||
* Default peripheral privacy configuration.
|
||||
*/
|
||||
static const central_privacy_configuration_t
|
||||
default_central_privacy_configuration;
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
public:
|
||||
void setEventHandler(EventHandler *handler);
|
||||
|
@ -343,11 +355,193 @@ public:
|
|||
*/
|
||||
ble_error_t setRandomStaticAddress(const ble::address_t &address);
|
||||
|
||||
ble::address_t getRandomStaticAddress();
|
||||
|
||||
#endif // !defined(DOXYGEN_ONLY)
|
||||
|
||||
/* ===================================================================== */
|
||||
/* private implementation follows */
|
||||
|
||||
private:
|
||||
/** List in random order */
|
||||
template<typename EventType, typename IndexType, IndexType MAX_EVENTS>
|
||||
class EventList {
|
||||
public:
|
||||
EventList()
|
||||
{
|
||||
};
|
||||
|
||||
~EventList()
|
||||
{
|
||||
for (IndexType i = 0; i < _current_size; ++i) {
|
||||
delete _pointers[i];
|
||||
}
|
||||
};
|
||||
|
||||
/** Add event to the list. List takes ownership of memory.
|
||||
*
|
||||
* @param event List will point to this event.
|
||||
* @return False if list full.
|
||||
*/
|
||||
bool push(EventType *event)
|
||||
{
|
||||
if (_current_size < MAX_EVENTS) {
|
||||
_pointers[_current_size] = event;
|
||||
_current_size++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/** Take one entry of the list. Transfers ownership to caller.
|
||||
*
|
||||
* @return The event return. Memory belongs to caller.
|
||||
*/
|
||||
EventType* pop()
|
||||
{
|
||||
MBED_ASSERT(_current_size);
|
||||
|
||||
if (!_current_size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventType* event_returned = _pointers[_current_index];
|
||||
|
||||
_current_size--;
|
||||
if (_current_size != _current_index) {
|
||||
_pointers[_current_index] = _pointers[_current_size];
|
||||
} else {
|
||||
_current_index = 0;
|
||||
}
|
||||
|
||||
return event_returned;
|
||||
};
|
||||
|
||||
/** Return pointer to the first element that fulfills the passed in condition and remove the entry
|
||||
* that was pointing to the item. Transfers ownership to caller.
|
||||
*
|
||||
* @param compare_func The condition that is checked for all the items.
|
||||
* @return First element that fulfills the passed in condition or nullptr if no such item found.
|
||||
*/
|
||||
EventType* pop(mbed::Callback<bool(EventType&)> compare_func)
|
||||
{
|
||||
for (IndexType i = 0; i < _current_size ; ++i) {
|
||||
if (compare_func(*_pointers[_current_index])) {
|
||||
return pop();
|
||||
}
|
||||
increment_current_index();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Return pointer to the first element that fulfills the passed in condition and remove the entry
|
||||
* that was pointing to the item. Takes and returns number of failed matches allowing to speed up search.
|
||||
* Transfers ownership to caller.
|
||||
*
|
||||
* @note Calls must be consecutive - any call to pop or find will invalidate the search.
|
||||
*
|
||||
* @param compare_func The condition that is checked for all the items.
|
||||
* @param events_not_matching Pointer to the number of items already searched but not matching.
|
||||
* This is updated in the method.
|
||||
* @return First element that fulfills the passed in condition or nullptr if no such item found.
|
||||
*/
|
||||
EventType* continue_pop(mbed::Callback<bool(EventType&)> compare_func, IndexType *events_not_matching)
|
||||
{
|
||||
_current_index = *events_not_matching;
|
||||
for (IndexType i = *events_not_matching; i < _current_size ; ++i) {
|
||||
if (compare_func(*_pointers[_current_index])) {
|
||||
return pop();
|
||||
}
|
||||
(*events_not_matching)++;
|
||||
increment_current_index();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Return pointer to the first element that fulfills the passed in condition. Does not remove item from list.
|
||||
*
|
||||
* @param compare_func The condition that is checked for all the items.
|
||||
* @return First element that fulfills the passed in condition or nullptr if no such item found.
|
||||
*/
|
||||
EventType* find(mbed::Callback<bool(EventType&)> compare_func)
|
||||
{
|
||||
for (IndexType i = 0; i < _current_size ; ++i) {
|
||||
if (compare_func(*_pointers[_current_index])) {
|
||||
return _pointers[_current_index];
|
||||
}
|
||||
increment_current_index();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** Return number of events stored.
|
||||
*
|
||||
* @return Number of events stored.
|
||||
*/
|
||||
IndexType get_size()
|
||||
{
|
||||
return _current_size;
|
||||
}
|
||||
|
||||
private:
|
||||
void increment_current_index()
|
||||
{
|
||||
_current_index++;
|
||||
if (_current_index == _current_size) {
|
||||
_current_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventType* _pointers[MAX_EVENTS];
|
||||
IndexType _current_size = 0;
|
||||
/* this helps us find the event faster */
|
||||
IndexType _current_index = 0;
|
||||
};
|
||||
|
||||
#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
class PendingAdvertisingReportEvent {
|
||||
public:
|
||||
PendingAdvertisingReportEvent(
|
||||
const AdvertisingReportEvent& event_to_copy
|
||||
) : event(event_to_copy)
|
||||
{
|
||||
/* copy the data to the buffer */
|
||||
const mbed::Span<const uint8_t> payload = event_to_copy.getPayload();
|
||||
if (payload.size()) {
|
||||
advertising_data_buffer = new(std::nothrow) uint8_t[payload.size()];
|
||||
if (advertising_data_buffer) {
|
||||
memcpy(advertising_data_buffer, payload.data(), payload.size());
|
||||
/* set the payload to our local copy of the data */
|
||||
event.setAdvertisingData(mbed::make_Span(advertising_data_buffer, payload.size()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
~PendingAdvertisingReportEvent()
|
||||
{
|
||||
delete[] advertising_data_buffer;
|
||||
}
|
||||
|
||||
bool is_valid()
|
||||
{
|
||||
return advertising_data_buffer || (event.getPayload().size() == 0);
|
||||
}
|
||||
|
||||
AdvertisingReportEvent& get_pending_event()
|
||||
{
|
||||
return event;
|
||||
}
|
||||
|
||||
private:
|
||||
AdvertisingReportEvent event;
|
||||
uint8_t *advertising_data_buffer = nullptr;
|
||||
};
|
||||
#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
private:
|
||||
/* Disallow copy and assignment. */
|
||||
Gap(const Gap &);
|
||||
|
@ -357,12 +551,15 @@ private:
|
|||
Gap(
|
||||
ble::PalEventQueue &event_queue,
|
||||
ble::PalGap &pal_gap,
|
||||
ble::PalGenericAccessService &generic_access_service,
|
||||
ble::PalSecurityManager &pal_sm
|
||||
ble::PalGenericAccessService &generic_access_service
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
, ble::PrivateAddressController &private_address_controller
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
);
|
||||
|
||||
~Gap();
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
ble_error_t setAdvertisingData(
|
||||
advertising_handle_t handle,
|
||||
Span<const uint8_t> payload,
|
||||
|
@ -373,11 +570,15 @@ private:
|
|||
void on_advertising_timeout();
|
||||
|
||||
void process_advertising_timeout();
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
void on_gap_event_received(const GapEvent &e);
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
void on_advertising_report(const GapAdvertisingReportEvent &e);
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
void on_connection_complete(const GapConnectionCompleteEvent &e);
|
||||
|
||||
void on_disconnection_complete(const GapDisconnectionCompleteEvent &e);
|
||||
|
@ -387,6 +588,7 @@ private:
|
|||
);
|
||||
|
||||
void on_connection_update(const GapConnectionUpdateEvent &e);
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
|
||||
void on_unexpected_error(const GapUnexpectedErrorEvent &e);
|
||||
|
||||
|
@ -399,35 +601,104 @@ private:
|
|||
|
||||
own_address_type_t get_own_address_type(AddressUseType_t address_use_type);
|
||||
|
||||
#if BLE_FEATURE_WHITELIST
|
||||
bool initialize_whitelist() const;
|
||||
#endif // BLE_FEATURE_WHITELIST
|
||||
|
||||
ble_error_t update_address_resolution_setting();
|
||||
|
||||
void set_random_address_rotation(bool enable);
|
||||
|
||||
void update_random_address();
|
||||
|
||||
bool getUnresolvableRandomAddress(ble::address_t &address);
|
||||
|
||||
void on_address_rotation_timeout();
|
||||
#if BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
ble_error_t update_ll_address_resolution_setting();
|
||||
#endif // BLE_FEATURE_PRIVACY && !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
ble_error_t setExtendedAdvertisingParameters(
|
||||
advertising_handle_t handle,
|
||||
const AdvertisingParameters ¶meters
|
||||
);
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
bool is_extended_advertising_available();
|
||||
|
||||
void prepare_legacy_advertising_set();
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
ble_error_t prepare_legacy_advertising_set(const AdvertisingParameters& parameters);
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
/** Call the internal handlers that report to the security manager and GATT
|
||||
* that a connection has been established.
|
||||
*
|
||||
* @param report Connection event
|
||||
*/
|
||||
void report_internal_connection_complete(const ConnectionCompleteEvent& report);
|
||||
|
||||
/** Pass the connection complete event to the application. This may involve privacy resolution.
|
||||
*
|
||||
* @param report Event to be passed to the user application.
|
||||
*/
|
||||
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
|
||||
);
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/** Pass the connection complete event to the application after privacy resolution completed.
|
||||
*
|
||||
* @param event Event to be passed to the user application.
|
||||
* @param identity_address_type Address type of the identity address.
|
||||
* @param identity_address Address resolved by private address resolution, nullptr if no identity found.
|
||||
*/
|
||||
void conclude_signal_connection_complete_after_address_resolution(
|
||||
ConnectionCompleteEvent &event,
|
||||
target_peer_address_type_t identity_address_type,
|
||||
const address_t *identity_address
|
||||
);
|
||||
#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
/** Pass the advertising report to the application. This may involve privacy resolution.
|
||||
*
|
||||
* @param report Report to be passed to the user application.
|
||||
*/
|
||||
void signal_advertising_report(AdvertisingReportEvent& report);
|
||||
|
||||
#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/** Pass the advertising report to the application after privacy resolution completed.
|
||||
*
|
||||
* @param event Event to be passed to the user application.
|
||||
* @param identity_address_type Address type of the identity address.
|
||||
* @param identity_address Address resolved by private address resolution, nullptr if no identity found.
|
||||
*/
|
||||
void conclude_signal_advertising_report_after_address_resolution(
|
||||
AdvertisingReportEvent &event,
|
||||
target_peer_address_type_t identity_address_type,
|
||||
const address_t *identity_address
|
||||
);
|
||||
#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
/* implements PalGap::EventHandler */
|
||||
private:
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
void on_read_phy(
|
||||
hci_error_code_t hci_status,
|
||||
connection_handle_t connection_handle,
|
||||
phy_t tx_phy,
|
||||
phy_t rx_phy
|
||||
) override;
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
void on_data_length_change(
|
||||
connection_handle_t connection_handle,
|
||||
|
@ -435,27 +706,17 @@ private:
|
|||
uint16_t rx_size
|
||||
) override;
|
||||
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
void on_phy_update_complete(
|
||||
hci_error_code_t hci_status,
|
||||
connection_handle_t connection_handle,
|
||||
phy_t tx_phy,
|
||||
phy_t rx_phy
|
||||
) override;
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
void on_enhanced_connection_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
connection_role_t own_role,
|
||||
connection_peer_address_type_t peer_address_type,
|
||||
const ble::address_t &peer_address,
|
||||
const ble::address_t &local_resolvable_private_address,
|
||||
const ble::address_t &peer_resolvable_private_address,
|
||||
uint16_t connection_interval,
|
||||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout,
|
||||
clock_accuracy_t master_clock_accuracy
|
||||
) override;
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
void on_extended_advertising_report(
|
||||
advertising_event_t event_type,
|
||||
const connection_peer_address_type_t *address_type,
|
||||
|
@ -471,7 +732,9 @@ private:
|
|||
uint8_t data_length,
|
||||
const uint8_t *data
|
||||
) override;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
void on_periodic_advertising_sync_established(
|
||||
hci_error_code_t error,
|
||||
sync_handle_t sync_handle,
|
||||
|
@ -493,6 +756,15 @@ private:
|
|||
) override;
|
||||
|
||||
void on_periodic_advertising_sync_loss(sync_handle_t sync_handle) override;
|
||||
#endif // BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
void on_legacy_advertising_started() override;
|
||||
|
||||
void on_legacy_advertising_stopped() override;
|
||||
|
||||
void on_advertising_set_started(const mbed::Span<const uint8_t>& handles) override;
|
||||
|
||||
void on_advertising_set_terminated(
|
||||
hci_error_code_t status,
|
||||
|
@ -506,7 +778,9 @@ private:
|
|||
connection_peer_address_type_t scanner_address_type,
|
||||
const ble::address_t &address
|
||||
) override;
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
void on_connection_update_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
|
@ -522,10 +796,56 @@ private:
|
|||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout
|
||||
) override;
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
void on_scan_started(bool success) override;
|
||||
|
||||
void on_scan_stopped(bool success) override;
|
||||
|
||||
void on_scan_timeout() override;
|
||||
|
||||
void process_legacy_scan_timeout();
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
/* Implement PrivateAddressController::EventHandler */
|
||||
private:
|
||||
void on_resolvable_private_addresses_generated(const address_t &address) final;
|
||||
|
||||
void on_non_resolvable_private_addresses_generated(const address_t &address) final;
|
||||
|
||||
void on_private_address_generated(bool connectable);
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
void on_address_resolution_completed(
|
||||
const address_t &peer_resolvable_address,
|
||||
bool resolved,
|
||||
target_peer_address_type_t identity_address_type,
|
||||
const address_t &identity_address
|
||||
) final;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
private:
|
||||
bool is_advertising() const;
|
||||
|
||||
bool is_radio_active() const;
|
||||
|
||||
void update_advertising_set_connectable_attribute(
|
||||
advertising_handle_t handle,
|
||||
const AdvertisingParameters& parameters
|
||||
);
|
||||
|
||||
enum class controller_operation_t {
|
||||
scanning, advertising, initiating
|
||||
};
|
||||
|
||||
const address_t *get_random_address(controller_operation_t operation, size_t advertising_set = 0);
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
void connecting_to_host_resolved_address_failed(bool inform_user = true);
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -539,28 +859,62 @@ private:
|
|||
*/
|
||||
ble::Gap::EventHandler *_event_handler;
|
||||
|
||||
#if BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
#if BLE_ROLE_OBSERVER
|
||||
EventList<PendingAdvertisingReportEvent, uint8_t, BLE_GAP_MAX_ADVERTISING_REPORTS_PENDING_ADDRESS_RESOLUTION> _reports_pending_address_resolution;
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
EventList<ConnectionCompleteEvent, uint8_t, DM_CONN_MAX> _connections_pending_address_resolution;
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
#endif // BLE_FEATURE_PRIVACY && BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
PalEventQueue &_event_queue;
|
||||
PalGap &_pal_gap;
|
||||
PalGenericAccessService &_gap_service;
|
||||
PalSecurityManager &_pal_sm;
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
PrivateAddressController &_private_address_controller;
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
ble::own_address_type_t _address_type;
|
||||
ble::address_t _address;
|
||||
initiator_policy_t _initiator_policy_mode;
|
||||
scanning_filter_policy_t _scanning_filter_policy;
|
||||
advertising_filter_policy_t _advertising_filter_policy;
|
||||
mutable whitelist_t _whitelist;
|
||||
|
||||
bool _privacy_enabled;
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
bool _privacy_initialization_pending = false;
|
||||
#if BLE_ROLE_PERIPHERAL
|
||||
peripheral_privacy_configuration_t _peripheral_privacy_configuration;
|
||||
#endif // BLE_ROLE_PERIPHERAL
|
||||
#if BLE_ROLE_OBSERVER
|
||||
central_privacy_configuration_t _central_privacy_configuration;
|
||||
#endif //BLE_ROLE_OBSERVER
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
ble::address_t _random_static_identity_address;
|
||||
bool _random_address_rotating;
|
||||
|
||||
bool _scan_enabled;
|
||||
|
||||
bool _scan_enabled = false;
|
||||
bool _scan_pending = false;
|
||||
bool _scan_interruptible = false;
|
||||
bool _scan_address_refresh = false;
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
enum class ConnectionToHostResolvedAddressState : uint8_t {
|
||||
idle,
|
||||
scan,
|
||||
connect
|
||||
};
|
||||
ble::address_t _connect_to_host_resolved_address;
|
||||
peer_address_type_t _connect_to_host_resolved_address_type = peer_address_type_t::ANONYMOUS;
|
||||
ConnectionToHostResolvedAddressState _connect_to_host_resolved_address_state = ConnectionToHostResolvedAddressState::idle;
|
||||
ConnectionParameters *_connect_to_host_resolved_address_parameters = nullptr;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
mbed::LowPowerTimeout _advertising_timeout;
|
||||
mbed::LowPowerTimeout _scan_timeout;
|
||||
mbed::LowPowerTicker _address_rotation_ticker;
|
||||
|
||||
bool _initiating = false;
|
||||
|
||||
template<size_t bit_size>
|
||||
struct BitArray {
|
||||
BitArray() : data()
|
||||
|
@ -612,6 +966,11 @@ private:
|
|||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _active_periodic_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _connectable_payload_size_exceeded;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _set_is_connectable;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _pending_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _address_refresh_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _interruptible_sets;
|
||||
BitArray<BLE_GAP_MAX_ADVERTISING_SETS> _adv_started_from_refresh;
|
||||
|
||||
|
||||
bool _user_manage_connection_parameter_requests : 1;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,745 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include "PrivateAddressController.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
PrivateAddressController::PrivateAddressController(
|
||||
PalPrivateAddressController &address_generator,
|
||||
PalEventQueue &event_queue,
|
||||
ble::resolvable_address_timeout_t rotation_timeout
|
||||
) :
|
||||
_pal(address_generator) ,
|
||||
_event_queue(event_queue),
|
||||
_rotation_timeout(rotation_timeout)
|
||||
{
|
||||
_pal.initialize();
|
||||
_pal.set_event_handler(this);
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
auto** next = &_free_resolution_entries;
|
||||
for (auto &entry : _resolution_list) {
|
||||
*next = &entry;
|
||||
next = &entry.next;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
}
|
||||
|
||||
PrivateAddressController::~PrivateAddressController()
|
||||
{
|
||||
clear_privacy_control_blocks();
|
||||
_pal.terminate();
|
||||
}
|
||||
|
||||
void PrivateAddressController::set_local_irk(const irk_t &local_irk)
|
||||
{
|
||||
_local_irk = local_irk;
|
||||
generate_resolvable_address();
|
||||
}
|
||||
|
||||
void PrivateAddressController::set_timeout(ble::resolvable_address_timeout_t rotation_timeout)
|
||||
{
|
||||
_rotation_timeout = rotation_timeout;
|
||||
_pal.set_ll_resolvable_private_address_timeout(rotation_timeout);
|
||||
if (_generation_started) {
|
||||
stop_private_address_generation();
|
||||
start_private_address_generation();
|
||||
}
|
||||
}
|
||||
|
||||
const address_t& PrivateAddressController::get_resolvable_private_address()
|
||||
{
|
||||
return _resolvable_address;
|
||||
}
|
||||
|
||||
const address_t& PrivateAddressController::get_non_resolvable_private_address()
|
||||
{
|
||||
return _non_resolvable_address;
|
||||
}
|
||||
|
||||
void PrivateAddressController::set_event_handler(EventHandler *handler)
|
||||
{
|
||||
_event_handler = handler;
|
||||
}
|
||||
|
||||
void PrivateAddressController::start_private_address_generation()
|
||||
{
|
||||
if (_generation_started) {
|
||||
return;
|
||||
}
|
||||
|
||||
// non resolvable private address generation has been delayed until now,
|
||||
// generate it.
|
||||
generate_non_resolvable_address();
|
||||
|
||||
_address_rotation_ticker.attach([this] {
|
||||
_event_queue.post([this]{
|
||||
generate_resolvable_address();
|
||||
generate_non_resolvable_address();
|
||||
});
|
||||
}, _rotation_timeout.valueChrono());
|
||||
_generation_started = true;
|
||||
}
|
||||
|
||||
void PrivateAddressController::stop_private_address_generation()
|
||||
{
|
||||
if (_generation_started) {
|
||||
_address_rotation_ticker.detach();
|
||||
_generation_started = false;
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::generate_resolvable_address()
|
||||
{
|
||||
if (_local_irk != irk_t{}) {
|
||||
_pal.generate_resolvable_private_address(_local_irk);
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::on_resolvable_private_address_generated(const address_t &rpa)
|
||||
{
|
||||
_resolvable_address = rpa;
|
||||
if (_event_handler) {
|
||||
_event_handler->on_resolvable_private_addresses_generated(_resolvable_address);
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::generate_non_resolvable_address()
|
||||
{
|
||||
_non_resolvable_address = _pal.generate_non_resolvable_private_address();
|
||||
_event_queue.post([this] {
|
||||
if (_event_handler) {
|
||||
_event_handler->on_non_resolvable_private_addresses_generated(_non_resolvable_address);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool PrivateAddressController::is_controller_privacy_supported()
|
||||
{
|
||||
return _pal.is_ll_privacy_supported();
|
||||
}
|
||||
|
||||
#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
ble_error_t PrivateAddressController::enable_controller_address_resolution(bool enable)
|
||||
{
|
||||
MBED_ASSERT(is_controller_privacy_supported());
|
||||
return _pal.set_ll_address_resolution(enable);
|
||||
}
|
||||
#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
uint8_t PrivateAddressController::read_resolving_list_capacity()
|
||||
{
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
return BLE_SECURITY_DATABASE_MAX_ENTRIES;
|
||||
#else
|
||||
if (is_controller_privacy_supported()) {
|
||||
return _pal.read_resolving_list_capacity();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif //BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
}
|
||||
|
||||
uint8_t PrivateAddressController::read_resolving_list_size()
|
||||
{
|
||||
return _resolving_list_size;
|
||||
}
|
||||
|
||||
ble_error_t PrivateAddressController::add_device_to_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t& peer_irk
|
||||
)
|
||||
{
|
||||
if (_local_irk == irk_t{}) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
// ensure an entry is not added twice
|
||||
for (auto &entry : _resolving_list) {
|
||||
if (entry.populated &&
|
||||
entry.peer_address_type == peer_address_type &&
|
||||
entry.peer_address == peer_identity_address &&
|
||||
entry.peer_irk == peer_irk
|
||||
) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool entry_added = false;
|
||||
for (auto &entry : _resolving_list) {
|
||||
if (entry.populated == false) {
|
||||
entry.peer_address_type = peer_address_type;
|
||||
entry.peer_address = peer_identity_address;
|
||||
entry.peer_irk = peer_irk;
|
||||
entry.populated = true;
|
||||
entry_added = true;
|
||||
_resolving_list_size++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry_added) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
|
||||
// Remove unresolved entries from the resolved list
|
||||
remove_resolution_entry_from_cache(
|
||||
[&](resolution_entry_t &entry) {
|
||||
return entry.identity == nullptr;
|
||||
}
|
||||
);
|
||||
|
||||
// reset pending resolution request
|
||||
restart_resolution_process_on_host();
|
||||
|
||||
return BLE_ERROR_NO_MEM;
|
||||
#else
|
||||
if (is_controller_privacy_supported()) {
|
||||
return queue_add_device_to_resolving_list(
|
||||
peer_address_type,
|
||||
peer_identity_address,
|
||||
peer_irk
|
||||
);
|
||||
} else {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
}
|
||||
|
||||
ble_error_t PrivateAddressController::remove_device_from_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
for (auto &entry : _resolving_list) {
|
||||
if (entry.populated &&
|
||||
entry.peer_address_type == peer_address_type &&
|
||||
entry.peer_address == peer_identity_address
|
||||
) {
|
||||
remove_resolution_entry_from_cache([&](resolution_entry_t& cache_entry) {
|
||||
return cache_entry.identity == &entry;
|
||||
});
|
||||
|
||||
entry.populated = false;
|
||||
_resolving_list_size--;
|
||||
|
||||
restart_resolution_process_on_host();
|
||||
}
|
||||
}
|
||||
return BLE_ERROR_NONE;
|
||||
#else
|
||||
if (is_controller_privacy_supported()) {
|
||||
return queue_remove_device_from_resolving_list(peer_address_type, peer_identity_address);
|
||||
} else {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
}
|
||||
|
||||
ble_error_t PrivateAddressController::clear_resolving_list()
|
||||
{
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
// Remove entry from the resolving list
|
||||
for (auto &entry : _resolving_list) {
|
||||
entry.populated = false;
|
||||
}
|
||||
// Remove all resolved entries from the cache
|
||||
remove_resolution_entry_from_cache([&](resolution_entry_t& entry) {
|
||||
return entry.identity != nullptr;
|
||||
});
|
||||
_resolving_list_size = 0;
|
||||
|
||||
restart_resolution_process_on_host();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
#else
|
||||
if (is_controller_privacy_supported()) {
|
||||
return queue_clear_resolving_list();
|
||||
} else {
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
}
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
bool PrivateAddressController::resolve_address_in_host_cache(
|
||||
const address_t &peer_address,
|
||||
target_peer_address_type_t *retrieved_address_type,
|
||||
const address_t **retrieved_address
|
||||
)
|
||||
{
|
||||
// An LRU cache is used, we first traverse the list of resolved address
|
||||
// and return any match
|
||||
auto *entry = _resolved_list;
|
||||
decltype(entry) previous = nullptr;
|
||||
while (entry) {
|
||||
if (entry->address == peer_address) {
|
||||
// The list contains resolved addresses AND unresolved addresses.
|
||||
// Fill input parameters accordingly
|
||||
if (entry->identity) {
|
||||
*retrieved_address = &entry->identity->peer_address;
|
||||
*retrieved_address_type = entry->identity->peer_address_type;
|
||||
} else {
|
||||
*retrieved_address = nullptr;
|
||||
}
|
||||
// update cache if we're not at the first entry
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
entry->next = _resolved_list;
|
||||
_resolved_list = entry;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ble_error_t PrivateAddressController::resolve_address_on_host(
|
||||
const address_t &peer_address,
|
||||
bool *resolution_complete,
|
||||
target_peer_address_type_t *retrieved_address_type,
|
||||
const address_t **retrieved_address
|
||||
)
|
||||
{
|
||||
*resolution_complete = resolve_address_in_host_cache(peer_address, retrieved_address_type, retrieved_address);
|
||||
|
||||
// In the case the address has not been resolved, we start the resolution
|
||||
// process.
|
||||
if (*resolution_complete) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return queue_resolve_address_on_host(peer_address);
|
||||
}
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
void PrivateAddressController::on_resolving_list_action_complete()
|
||||
{
|
||||
process_privacy_control_blocks(true);
|
||||
}
|
||||
|
||||
struct PrivateAddressController::PrivacyControlBlock {
|
||||
PrivacyControlBlock() : _next(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PrivacyControlBlock() = default;
|
||||
|
||||
// return trie if the handler has completed and false otherwise.
|
||||
virtual bool execute(PrivateAddressController& self) = 0;
|
||||
|
||||
void set_next(PrivacyControlBlock *next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
PrivacyControlBlock *next() const
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
private:
|
||||
PrivacyControlBlock *_next;
|
||||
};
|
||||
|
||||
#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
struct PrivateAddressController::PrivacyAddDevToResListControlBlock final :
|
||||
PrivateAddressController::PrivacyControlBlock {
|
||||
PrivacyAddDevToResListControlBlock(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
) : PrivacyControlBlock(),
|
||||
_peer_identity_address_type(peer_identity_address_type),
|
||||
_peer_identity_address(peer_identity_address),
|
||||
_peer_irk(peer_irk)
|
||||
{
|
||||
}
|
||||
|
||||
bool execute(PrivateAddressController& self) final
|
||||
{
|
||||
// Execute command
|
||||
self._pal.add_device_to_resolving_list(
|
||||
_peer_identity_address_type,
|
||||
_peer_identity_address,
|
||||
_peer_irk,
|
||||
self._local_irk
|
||||
);
|
||||
self._resolving_list_size++;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_peer_address_type_t _peer_identity_address_type;
|
||||
address_t _peer_identity_address;
|
||||
irk_t _peer_irk;
|
||||
};
|
||||
|
||||
ble_error_t PrivateAddressController::queue_add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
)
|
||||
{
|
||||
auto *cb = new(std::nothrow) PrivacyAddDevToResListControlBlock(
|
||||
peer_identity_address_type,
|
||||
peer_identity_address,
|
||||
peer_irk
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
struct PrivateAddressController::PrivacyRemoveDevFromResListControlBlock final :
|
||||
PrivateAddressController::PrivacyControlBlock {
|
||||
PrivacyRemoveDevFromResListControlBlock(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) : PrivacyControlBlock(),
|
||||
_peer_identity_address_type(peer_identity_address_type),
|
||||
_peer_identity_address(peer_identity_address)
|
||||
{
|
||||
}
|
||||
|
||||
bool execute(PrivateAddressController& self) final
|
||||
{
|
||||
// Execute command
|
||||
self._pal.remove_device_from_resolving_list(
|
||||
_peer_identity_address_type,
|
||||
_peer_identity_address
|
||||
);
|
||||
self._resolving_list_size--;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
advertising_peer_address_type_t _peer_identity_address_type;
|
||||
address_t _peer_identity_address;
|
||||
};
|
||||
|
||||
ble_error_t PrivateAddressController::queue_remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
)
|
||||
{
|
||||
auto *cb = new(std::nothrow) PrivacyRemoveDevFromResListControlBlock(
|
||||
peer_identity_address_type,
|
||||
peer_identity_address
|
||||
);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
struct PrivateAddressController::PrivacyClearResListControlBlock final :
|
||||
PrivateAddressController::PrivacyControlBlock {
|
||||
PrivacyClearResListControlBlock() : PrivacyControlBlock()
|
||||
{
|
||||
}
|
||||
|
||||
bool execute(PrivateAddressController& self) final
|
||||
{
|
||||
// Execute command
|
||||
self._pal.clear_resolving_list();
|
||||
self._resolving_list_size = 0;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
ble_error_t PrivateAddressController::queue_clear_resolving_list()
|
||||
{
|
||||
// Remove any pending control blocks, there's no point executing them as we're about to queue the list
|
||||
clear_privacy_control_blocks();
|
||||
|
||||
auto *cb = new(std::nothrow) PrivacyClearResListControlBlock();
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
queue_privacy_control_block(cb);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
#endif // !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
struct PrivateAddressController::PrivacyResolveAddressOnHost final :
|
||||
PrivateAddressController::PrivacyControlBlock {
|
||||
PrivacyResolveAddressOnHost(const address_t &peer_address) :
|
||||
PrivacyControlBlock(),
|
||||
peer_address(peer_address)
|
||||
{
|
||||
}
|
||||
|
||||
bool execute(PrivateAddressController& self) final
|
||||
{
|
||||
if (!self._resolving_list[resolving_list_index].populated) {
|
||||
// no entry at index 0, move to the next
|
||||
return start_next_resolution_round(self);
|
||||
} else {
|
||||
// start the resolution process with the first entry on the list
|
||||
start_resolution(self);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool on_resolution_complete(PrivateAddressController& self, bool resolved)
|
||||
{
|
||||
if (require_restart) {
|
||||
require_restart = false;
|
||||
resolving_list_index = 0;
|
||||
return execute(self);
|
||||
} else if (resolved) {
|
||||
notify_completion(
|
||||
self, peer_address, resolved,
|
||||
&self._resolving_list[resolving_list_index]
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
return start_next_resolution_round(self);
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
require_restart = true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool start_next_resolution_round(PrivateAddressController& self) {
|
||||
do {
|
||||
++resolving_list_index;
|
||||
if (resolving_list_index == BLE_SECURITY_DATABASE_MAX_ENTRIES) {
|
||||
notify_completion(self, peer_address,false,nullptr);
|
||||
return true;
|
||||
}
|
||||
} while (!self._resolving_list[resolving_list_index].populated);
|
||||
|
||||
start_resolution(self);
|
||||
return false;
|
||||
}
|
||||
|
||||
void start_resolution(PrivateAddressController& self) {
|
||||
self._pal.resolve_private_address(
|
||||
peer_address,
|
||||
self._resolving_list[resolving_list_index].peer_irk
|
||||
);
|
||||
}
|
||||
|
||||
void notify_completion(
|
||||
PrivateAddressController& self,
|
||||
const address_t &peer_resolvable_address,
|
||||
bool resolved,
|
||||
resolving_list_entry_t* identity
|
||||
)
|
||||
{
|
||||
// First we had the device to the resolution list
|
||||
self.add_resolution_entry_to_cache(peer_resolvable_address, identity);
|
||||
|
||||
if (!self._event_handler) {
|
||||
return;
|
||||
}
|
||||
self._event_handler->on_address_resolution_completed(
|
||||
peer_resolvable_address,
|
||||
resolved,
|
||||
identity ? identity->peer_address_type : target_peer_address_type_t::PUBLIC,
|
||||
identity ? identity->peer_address : address_t{}
|
||||
);
|
||||
}
|
||||
|
||||
size_t resolving_list_index = 0;
|
||||
address_t peer_address;
|
||||
bool require_restart = false;
|
||||
};
|
||||
|
||||
ble_error_t PrivateAddressController::queue_resolve_address_on_host(const address_t &peer_address)
|
||||
{
|
||||
auto *cb = new(std::nothrow) PrivacyResolveAddressOnHost(peer_address);
|
||||
if (cb == nullptr) {
|
||||
// Cannot go further
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
_event_queue.post([this, cb] {
|
||||
queue_privacy_control_block(cb);
|
||||
});
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void PrivateAddressController::restart_resolution_process_on_host()
|
||||
{
|
||||
// if processing is active, restart the one running.
|
||||
if (_processing_privacy_control_block && _pending_privacy_control_blocks) {
|
||||
static_cast<PrivacyResolveAddressOnHost*>(_pending_privacy_control_blocks)->invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::on_private_address_resolved(bool success)
|
||||
{
|
||||
if (_pending_privacy_control_blocks == nullptr ||
|
||||
_processing_privacy_control_block == false
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* cb = static_cast<PrivacyResolveAddressOnHost*>(_pending_privacy_control_blocks);
|
||||
bool completed = cb->on_resolution_complete(*this, success);
|
||||
process_privacy_control_blocks(completed);
|
||||
}
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
void PrivateAddressController::clear_privacy_control_blocks()
|
||||
{
|
||||
while (_pending_privacy_control_blocks != nullptr) {
|
||||
PrivacyControlBlock *next = _pending_privacy_control_blocks->next();
|
||||
delete _pending_privacy_control_blocks;
|
||||
_pending_privacy_control_blocks = next;
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::queue_privacy_control_block(PrivacyControlBlock *block)
|
||||
{
|
||||
if (_pending_privacy_control_blocks == nullptr) {
|
||||
_pending_privacy_control_blocks = block;
|
||||
} else {
|
||||
PrivacyControlBlock *node = _pending_privacy_control_blocks;
|
||||
while (node->next() != nullptr) {
|
||||
node = node->next();
|
||||
}
|
||||
node->set_next(block);
|
||||
}
|
||||
|
||||
process_privacy_control_blocks(false);
|
||||
}
|
||||
|
||||
// If cb_completed is set to true, it means the previous control block has completed
|
||||
|
||||
void PrivateAddressController::process_privacy_control_blocks(bool cb_completed)
|
||||
{
|
||||
if ((_processing_privacy_control_block == true) && !cb_completed) {
|
||||
// Busy, cannot process next control block for now
|
||||
return;
|
||||
}
|
||||
|
||||
if (cb_completed && _pending_privacy_control_blocks) {
|
||||
auto *next = _pending_privacy_control_blocks->next();
|
||||
delete _pending_privacy_control_blocks;
|
||||
_pending_privacy_control_blocks = next;
|
||||
}
|
||||
|
||||
auto *cb = _pending_privacy_control_blocks;
|
||||
if (cb == nullptr) {
|
||||
// All control blocks processed
|
||||
_processing_privacy_control_block = false;
|
||||
return;
|
||||
}
|
||||
|
||||
while (cb) {
|
||||
bool completed = cb->execute(*this);
|
||||
if (completed) {
|
||||
auto *next = cb->next();
|
||||
delete cb;
|
||||
cb = next;
|
||||
} else {
|
||||
_processing_privacy_control_block = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_pending_privacy_control_blocks = cb;
|
||||
}
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
template<typename Pred>
|
||||
void PrivateAddressController::remove_resolution_entry_from_cache(const Pred &predicate)
|
||||
{
|
||||
resolution_entry_t* previous = nullptr;
|
||||
resolution_entry_t* entry = _resolved_list;
|
||||
while (entry) {
|
||||
if (predicate(*entry)) {
|
||||
if (previous) {
|
||||
previous->next = entry->next;
|
||||
} else {
|
||||
_resolved_list = entry->next;
|
||||
}
|
||||
entry->next = _free_resolution_entries;
|
||||
_free_resolution_entries = entry;
|
||||
if (previous) {
|
||||
entry = previous->next;
|
||||
} else {
|
||||
entry = _resolved_list;
|
||||
}
|
||||
} else {
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateAddressController::add_resolution_entry_to_cache(
|
||||
const address_t& address, resolving_list_entry_t* identity
|
||||
)
|
||||
{
|
||||
resolution_entry_t* entry = nullptr;
|
||||
if (_free_resolution_entries) {
|
||||
entry = _free_resolution_entries;
|
||||
_free_resolution_entries = entry->next;
|
||||
} else {
|
||||
// retrieve the last entry in the resolved list
|
||||
entry = _resolved_list;
|
||||
resolution_entry_t *previous = nullptr;
|
||||
while (entry->next) {
|
||||
previous = entry;
|
||||
entry = entry->next;
|
||||
}
|
||||
previous->next = nullptr;
|
||||
}
|
||||
|
||||
// Update the entry and insert it at the top of the list
|
||||
entry->address = address;
|
||||
entry->identity = identity;
|
||||
entry->next = _resolved_list;
|
||||
_resolved_list = entry;
|
||||
}
|
||||
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
|
@ -0,0 +1,351 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H
|
||||
#define BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "drivers/LowPowerTicker.h"
|
||||
#include "ble/common/BLETypes.h"
|
||||
#include "ble/common/blecommon.h"
|
||||
#include "source/pal/PalEventQueue.h"
|
||||
#include "source/pal/PalPrivateAddressController.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
/**
|
||||
* This module generate resolvable and non resolvable private addresses usable
|
||||
* by Gap when it advertise, scan or connect to a peer.
|
||||
* It also manages the LL resolvable private address resolution and offer software
|
||||
* workaround to resolve addresses on the host.
|
||||
*/
|
||||
class PrivateAddressController : private PalPrivateAddressController::EventHandler {
|
||||
public:
|
||||
struct EventHandler {
|
||||
/**
|
||||
* Called when a new resolvable private address has been generated.
|
||||
* @param address The resolvable private address generated.
|
||||
*/
|
||||
virtual void on_resolvable_private_addresses_generated(
|
||||
const address_t &address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Called when a new non resolvable private address has been generated.
|
||||
* @param address The non resolvable private address generated.
|
||||
*/
|
||||
virtual void on_non_resolvable_private_addresses_generated(
|
||||
const address_t &address
|
||||
) = 0;
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/**
|
||||
* Called when address resolution has been completed by the host.
|
||||
*
|
||||
* @note Address resolution process is completly transparent when done
|
||||
* in LL.
|
||||
*
|
||||
* @param peer_resolvable_address The resolvable address that was being
|
||||
* resolved.
|
||||
* @param resolved Indicate if the address has been resolved or not with
|
||||
* local irks. If false, the params identity_address_type and
|
||||
* identity_address are not valid.
|
||||
* @param identity_address_type The type of the identity address resolved.
|
||||
* @param identity_address The identity address resolved.
|
||||
*/
|
||||
virtual void on_address_resolution_completed(
|
||||
const address_t &peer_resolvable_address,
|
||||
bool resolved,
|
||||
target_peer_address_type_t identity_address_type,
|
||||
const address_t &identity_address
|
||||
) = 0;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new PrivateAddressController.
|
||||
* @param pal_address_controller Reference to the underlying pal.
|
||||
* @param event_queue Reference to the event queue running in the stack
|
||||
* context.
|
||||
* @param rotation_timeout Time after which private addresses must be renew.
|
||||
*/
|
||||
PrivateAddressController(
|
||||
PalPrivateAddressController &pal_address_controller,
|
||||
PalEventQueue &event_queue,
|
||||
ble::resolvable_address_timeout_t rotation_timeout
|
||||
);
|
||||
|
||||
~PrivateAddressController();
|
||||
|
||||
PrivateAddressController(const PrivateAddressController&) = delete;
|
||||
PrivateAddressController& operator=(const PrivateAddressController&) = delete;
|
||||
|
||||
/**
|
||||
* Set the local irk used for address generation. Generation doesn't start
|
||||
* until a valid irk has been set.
|
||||
* @param local_irk
|
||||
*/
|
||||
void set_local_irk(const irk_t &local_irk);
|
||||
|
||||
/**
|
||||
* Change address renewal timeout.
|
||||
* @param rotation_timeout address generation timeout.
|
||||
*/
|
||||
void set_timeout(ble::resolvable_address_timeout_t rotation_timeout);
|
||||
|
||||
/**
|
||||
* Get the current resolvable private address.
|
||||
*/
|
||||
const address_t& get_resolvable_private_address();
|
||||
|
||||
/**
|
||||
* Get the current non resolvable private address.
|
||||
*/
|
||||
const address_t& get_non_resolvable_private_address();
|
||||
|
||||
/**
|
||||
* Set the event handler catching events from this instance.
|
||||
*/
|
||||
void set_event_handler(EventHandler *handler);
|
||||
|
||||
/**
|
||||
* Start private address generation. A new address is generated when the
|
||||
* timeout expired.
|
||||
* it ends when stop_private_address_generation is called.
|
||||
*/
|
||||
void start_private_address_generation();
|
||||
|
||||
/**
|
||||
* Stop private address generation.
|
||||
*/
|
||||
void stop_private_address_generation();
|
||||
|
||||
/**
|
||||
* Return true if privacy is supported by the underlying controller and false
|
||||
* otherwise.
|
||||
*/
|
||||
bool is_controller_privacy_supported();
|
||||
|
||||
#if !BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/**
|
||||
* Enable address resolution by the controller.
|
||||
*/
|
||||
ble_error_t enable_controller_address_resolution(bool enable);
|
||||
#endif //!BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
/**
|
||||
* Read the number of entries that can be put in the resolving list.
|
||||
*/
|
||||
uint8_t read_resolving_list_capacity();
|
||||
|
||||
/**
|
||||
* Read the number of entries that are in the resolving list.
|
||||
*/
|
||||
uint8_t read_resolving_list_size();
|
||||
|
||||
/**
|
||||
* Add a new peer to the resolving list.
|
||||
* @param peer_address_type The type of the peer's identity address.
|
||||
* @param peer_identity_address The identity address of the peer.
|
||||
* @param peer_irk The IRK of the peer.
|
||||
* @return BLE_ERROR_NONE in case of success and false otherwise.
|
||||
*/
|
||||
ble_error_t add_device_to_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t& peer_irk
|
||||
);
|
||||
|
||||
/**
|
||||
* Remove a device from the resolving list.
|
||||
* @param peer_address_type The type of the peer's identity address.
|
||||
* @param peer_identity_address The identity address of the peer.
|
||||
* @return
|
||||
*/
|
||||
ble_error_t remove_device_from_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
);
|
||||
|
||||
/**
|
||||
* Empty the resolving list.
|
||||
*/
|
||||
ble_error_t clear_resolving_list();
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/**
|
||||
* Resolve a private resolvable address on the host.
|
||||
*
|
||||
* To speedup operations, this module uses a cache to avoid too many
|
||||
* resolutions. If the entry is available in the cache, it is returned
|
||||
* immediately otherwise, the request will be completed by a report through
|
||||
* EventHandler::on_address_resolution_completed
|
||||
*
|
||||
* @param peer_address the address to resolve.
|
||||
* @param resolution_complete Set to true if the resolution process has been
|
||||
* completed. If false, result will be made available by
|
||||
* EventHandler::on_address_resolution_completed.
|
||||
* @param retrieved_address_type The type of the address resolved. Valid if
|
||||
* resolution_complete is equals to true AND retrieved_address is not null.
|
||||
* @param retrieved_address If an entry has been found for the address in
|
||||
* input this will be set to null if the address has not been resolved with
|
||||
* the local irks or a pointer to the identity address if it has been resolved.
|
||||
*/
|
||||
ble_error_t resolve_address_on_host(
|
||||
const address_t &peer_address,
|
||||
bool *resolution_complete,
|
||||
target_peer_address_type_t *retrieved_address_type,
|
||||
const address_t **retrieved_address
|
||||
);
|
||||
/**
|
||||
* Resolve a private address by looking in the cache.
|
||||
*
|
||||
* @param peer_address the address to resolve.
|
||||
* @param retrieved_address_type The type of the address resolved. Valid if
|
||||
* resolution_complete is equals to true AND retrieved_address is not null.
|
||||
* @param retrieved_address If an entry has been found for the address in
|
||||
* input this will be set to null if the address has not been resolved with
|
||||
* the local irks or a pointer to the identity address if it has been resolved.
|
||||
*
|
||||
* @return True if the address has been found in cache.
|
||||
*/
|
||||
bool resolve_address_in_host_cache(
|
||||
const address_t &peer_address,
|
||||
target_peer_address_type_t *retrieved_address_type,
|
||||
const address_t **retrieved_address
|
||||
);
|
||||
|
||||
/**
|
||||
* Resolve a private resolvable address asynchronously. The request will be completed by a report through
|
||||
* EventHandler::on_address_resolution_completed.
|
||||
*
|
||||
* @param peer_address the address to resolve.
|
||||
*/
|
||||
ble_error_t queue_resolve_address_on_host(const address_t &peer_address);
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
private:
|
||||
|
||||
void generate_resolvable_address();
|
||||
|
||||
void generate_non_resolvable_address();
|
||||
|
||||
// EventHandler implementation
|
||||
void on_resolvable_private_address_generated(const address_t &rpa) final;
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
void on_private_address_resolved(bool success) final;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
void on_resolving_list_action_complete() final;
|
||||
|
||||
// --- resolving list and resolution management
|
||||
// The same list is shared between the two processes given they will never
|
||||
// be active at the same time. Either the controller supports LL resolution
|
||||
// and the list will only contain resolving list update operations or the
|
||||
// controller doesn't support LL and address resolution is the only operation
|
||||
// present in the operation list.
|
||||
struct PrivacyControlBlock;
|
||||
struct PrivacyClearResListControlBlock;
|
||||
struct PrivacyAddDevToResListControlBlock;
|
||||
struct PrivacyRemoveDevFromResListControlBlock;
|
||||
|
||||
// Queue control block to add device to resolving list
|
||||
ble_error_t queue_add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
);
|
||||
|
||||
// Queue control block to remove device from resolving list
|
||||
ble_error_t queue_remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
);
|
||||
|
||||
// Queue control block to clear resolving list
|
||||
ble_error_t queue_clear_resolving_list();
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
struct PrivacyResolveAddressOnHost;
|
||||
|
||||
void restart_resolution_process_on_host();
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
// Clear all control blocks
|
||||
void clear_privacy_control_blocks();
|
||||
|
||||
// Queue a control block
|
||||
void queue_privacy_control_block(PrivacyControlBlock *block);
|
||||
|
||||
// Try to dequeue and process the next control block.
|
||||
// cb_completed is set when the previous block has completed
|
||||
void process_privacy_control_blocks(bool cb_completed);
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
struct resolving_list_entry_t;
|
||||
|
||||
template<typename Pred>
|
||||
void remove_resolution_entry_from_cache(const Pred& predicate);
|
||||
|
||||
void add_resolution_entry_to_cache(const address_t& address, resolving_list_entry_t* identity);
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
PalPrivateAddressController &_pal;
|
||||
PalEventQueue &_event_queue;
|
||||
ble::resolvable_address_timeout_t _rotation_timeout;
|
||||
bool _generation_started;
|
||||
irk_t _local_irk = {};
|
||||
EventHandler *_event_handler = nullptr;
|
||||
mbed::LowPowerTicker _address_rotation_ticker;
|
||||
address_t _resolvable_address = {};
|
||||
address_t _non_resolvable_address = {};
|
||||
|
||||
PrivacyControlBlock *_pending_privacy_control_blocks = nullptr;
|
||||
bool _processing_privacy_control_block = false;
|
||||
|
||||
uint8_t _resolving_list_size = 0;
|
||||
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
struct resolving_list_entry_t {
|
||||
address_t peer_address = {};
|
||||
irk_t peer_irk = {};
|
||||
target_peer_address_type_t peer_address_type = target_peer_address_type_t::PUBLIC;
|
||||
bool populated = false;
|
||||
};
|
||||
|
||||
resolving_list_entry_t _resolving_list[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
||||
|
||||
struct resolution_entry_t {
|
||||
address_t address = address_t {};
|
||||
resolution_entry_t *next = nullptr;
|
||||
resolving_list_entry_t *identity = nullptr;
|
||||
};
|
||||
|
||||
resolution_entry_t _resolution_list[BLE_GAP_HOST_PRIVACY_RESOLVED_CACHE_SIZE];
|
||||
resolution_entry_t *_resolved_list = nullptr;
|
||||
resolution_entry_t *_free_resolution_entries = nullptr;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#endif //BLE_GENERIC_PRIVATE_ADDRESS_CONTROLLER_H
|
|
@ -168,16 +168,26 @@ public:
|
|||
*/
|
||||
virtual void get_entry_local_keys(
|
||||
SecurityEntryKeysDbCb_t cb,
|
||||
entry_handle_t db_handle,
|
||||
entry_handle_t* db_handle,
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(*db_handle);
|
||||
/* validate we have the correct key */
|
||||
if (keys && ediv == keys->ediv && rand == keys->rand) {
|
||||
cb(db_handle, keys);
|
||||
cb(*db_handle, keys);
|
||||
} else {
|
||||
cb(db_handle, NULL);
|
||||
// Maybe this isn't the correct entry, try to find one that matches
|
||||
entry_handle_t correct_handle = find_entry_by_peer_ediv_rand(ediv, rand);
|
||||
if (!correct_handle) {
|
||||
cb(*db_handle, NULL);
|
||||
}
|
||||
// Note: keys should never be null as a matching entry has been retrieved
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(correct_handle);
|
||||
MBED_ASSERT(keys);
|
||||
close_entry(*db_handle, false);
|
||||
*db_handle = correct_handle;
|
||||
cb(*db_handle, keys);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,6 +460,20 @@ public:
|
|||
return _local_identity.irk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return local identity address.
|
||||
*/
|
||||
virtual const address_t& get_local_identity_address() {
|
||||
return _local_identity.identity_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the local identity address is public or not
|
||||
*/
|
||||
virtual bool is_local_identity_address_public() {
|
||||
return _local_identity.identity_address_is_public;
|
||||
}
|
||||
|
||||
/* list management */
|
||||
|
||||
/**
|
||||
|
@ -538,17 +562,53 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a database entry based on ediv and rand.
|
||||
*
|
||||
* @param[in] ediv E diversifier
|
||||
* @param[in] rand random part
|
||||
*
|
||||
* @return A handle to the entry.
|
||||
*/
|
||||
virtual entry_handle_t find_entry_by_peer_ediv_rand(
|
||||
const ediv_t &ediv,
|
||||
const rand_t &rand
|
||||
) {
|
||||
for (size_t i = 0; i < get_entry_count(); i++) {
|
||||
entry_handle_t db_handle = get_entry_handle_by_index(i);
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
|
||||
if (!flags || flags->connected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SecurityEntryKeys_t* keys = read_in_entry_local_keys(db_handle);
|
||||
if (!keys) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keys->ediv == ediv && keys->rand == rand) {
|
||||
return db_handle;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close a connection entry.
|
||||
*
|
||||
* @param[in] db_handle this handle will be freed up from the security db.
|
||||
*/
|
||||
virtual void close_entry(entry_handle_t db_handle) {
|
||||
virtual void close_entry(entry_handle_t db_handle, bool require_sync = true) {
|
||||
SecurityDistributionFlags_t* flags = get_distribution_flags(db_handle);
|
||||
if (flags) {
|
||||
flags->connected = false;
|
||||
}
|
||||
sync(db_handle);
|
||||
if (require_sync) {
|
||||
sync(db_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if BLE_FEATURE_SECURITY
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/common/BLERoles.h"
|
||||
|
||||
|
@ -134,7 +136,7 @@ ble_error_t SecurityManager::init(
|
|||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
// set the local identity address and irk
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
if (result == BLE_ERROR_NONE) {
|
||||
result = init_identity();
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
@ -739,12 +741,16 @@ ble_error_t SecurityManager::getSigningKey(connection_handle_t connection, bool
|
|||
// Privacy
|
||||
//
|
||||
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t SecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds)
|
||||
{
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_private_address_timeout(timeout_in_seconds);
|
||||
_private_address_controller.set_timeout(
|
||||
resolvable_address_timeout_t(timeout_in_seconds)
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Authentication
|
||||
|
@ -977,13 +983,13 @@ ble_error_t SecurityManager::init_database(
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t SecurityManager::init_resolving_list()
|
||||
{
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
|
||||
/* match the resolving list to the currently stored set of IRKs */
|
||||
uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity();
|
||||
uint8_t resolving_list_capacity = _private_address_controller.read_resolving_list_capacity();
|
||||
auto* identity_list_p =
|
||||
new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
|
||||
|
||||
|
@ -1003,8 +1009,9 @@ ble_error_t SecurityManager::init_resolving_list()
|
|||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
|
||||
#if BLE_FEATURE_SIGNING
|
||||
ble_error_t SecurityManager::init_signing()
|
||||
{
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
|
@ -1025,16 +1032,36 @@ ble_error_t SecurityManager::init_signing()
|
|||
|
||||
return _pal.set_csrk(*pcsrk, local_sign_counter);
|
||||
}
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t SecurityManager::init_identity()
|
||||
{
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
const irk_t *pirk = nullptr;
|
||||
|
||||
ble::Gap& gap = BLE::Instance().gap();
|
||||
|
||||
irk_t irk = _db->get_local_irk();
|
||||
address_t identity_address;
|
||||
bool public_identity_address = false;
|
||||
if (irk != irk_t()) {
|
||||
pirk = &irk;
|
||||
public_identity_address = _db->is_local_identity_address_public();
|
||||
identity_address = _db->get_local_identity_address();
|
||||
|
||||
if (!_db->is_local_identity_address_public()) {
|
||||
// Some controllers doesn't store their random static address and
|
||||
// instead generates them at each reboot.
|
||||
// The code should replace the random static address with the identity
|
||||
// address if this is the case.
|
||||
if (_db->get_local_identity_address() != gap.getRandomStaticAddress()) {
|
||||
ble_error_t err = gap.setRandomStaticAddress(_db->get_local_identity_address());
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ble_error_t ret = get_random_data(irk.data(), irk.size());
|
||||
if (ret != BLE_ERROR_NONE) {
|
||||
|
@ -1042,18 +1069,19 @@ ble_error_t SecurityManager::init_identity()
|
|||
}
|
||||
|
||||
pirk = &irk;
|
||||
address_t identity_address;
|
||||
bool public_address;
|
||||
ret = _pal.get_identity_address(identity_address, public_address);
|
||||
if (ret != BLE_ERROR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
_db->set_local_identity(irk, identity_address, public_address);
|
||||
public_identity_address = false;
|
||||
identity_address = gap.getRandomStaticAddress();
|
||||
_db->set_local_identity(irk, identity_address, public_identity_address);
|
||||
}
|
||||
|
||||
return _pal.set_irk(*pirk);
|
||||
auto err = _pal.set_irk(*pirk);
|
||||
if (!err) {
|
||||
_private_address_controller.set_local_irk(*pirk);
|
||||
_pal.set_identity_address(identity_address, public_identity_address);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
ble_error_t SecurityManager::get_random_data(uint8_t *buffer, size_t size)
|
||||
{
|
||||
|
@ -1342,7 +1370,7 @@ void SecurityManager::on_security_entry_retrieved(
|
|||
|
||||
typedef advertising_peer_address_type_t address_type_t;
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
_pal.add_device_to_resolving_list(
|
||||
_private_address_controller.add_device_to_resolving_list(
|
||||
identity->identity_address_is_public ?
|
||||
address_type_t::PUBLIC :
|
||||
address_type_t::RANDOM,
|
||||
|
@ -1360,9 +1388,10 @@ void SecurityManager::on_identity_list_retrieved(
|
|||
{
|
||||
typedef advertising_peer_address_type_t address_type_t;
|
||||
|
||||
_pal.clear_resolving_list();
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
_private_address_controller.clear_resolving_list();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
_pal.add_device_to_resolving_list(
|
||||
_private_address_controller.add_device_to_resolving_list(
|
||||
identity_list[i].identity_address_is_public ?
|
||||
address_type_t::PUBLIC :
|
||||
address_type_t::RANDOM,
|
||||
|
@ -1370,6 +1399,7 @@ void SecurityManager::on_identity_list_retrieved(
|
|||
identity_list[i].irk
|
||||
);
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
delete [] identity_list.data();
|
||||
}
|
||||
|
@ -1912,7 +1942,7 @@ void SecurityManager::on_ltk_request(
|
|||
|
||||
_db->get_entry_local_keys(
|
||||
mbed::callback(this, &SecurityManager::set_ltk_cb),
|
||||
cb->db_entry,
|
||||
&cb->db_entry,
|
||||
ediv,
|
||||
rand
|
||||
);
|
||||
|
@ -2057,3 +2087,5 @@ void SecurityManager::setSecurityManagerEventHandler(EventHandler* handler)
|
|||
|
||||
} /* namespace impl */
|
||||
} /* namespace ble */
|
||||
|
||||
#endif // BLE_FEATURE_SECURITY
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "source/pal/PalSecurityManager.h"
|
||||
|
||||
#include "source/generic/SecurityDb.h"
|
||||
|
||||
#include "source/generic/PrivateAddressController.h"
|
||||
|
||||
namespace ble {
|
||||
class PalGenericAccessService;
|
||||
|
@ -185,9 +185,11 @@ public:
|
|||
// Privacy
|
||||
//
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t setPrivateAddressTimeout(
|
||||
uint16_t timeout_in_seconds
|
||||
);
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
/* Event callback handlers. */
|
||||
public:
|
||||
|
@ -452,11 +454,17 @@ public:
|
|||
ble::PalSecurityManager &palImpl,
|
||||
ble::PalConnectionMonitor &connMonitorImpl,
|
||||
ble::PalSigningMonitor &signingMonitorImpl
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
, PrivateAddressController &privateAddressController
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
) : eventHandler(nullptr),
|
||||
_pal(palImpl),
|
||||
_connection_monitor(connMonitorImpl),
|
||||
_signing_monitor(signingMonitorImpl),
|
||||
_db(nullptr),
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
_private_address_controller(privateAddressController),
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
_default_authentication(0),
|
||||
_default_key_distribution(KeyDistribution::KEY_DISTRIBUTION_ALL),
|
||||
_pairing_authorisation_required(false),
|
||||
|
@ -491,11 +499,17 @@ private:
|
|||
|
||||
ble_error_t init_database(const char *db_path = nullptr);
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t init_resolving_list();
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#if BLE_FEATURE_SIGNING
|
||||
ble_error_t init_signing();
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ble_error_t init_identity();
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
ble_error_t get_random_data(
|
||||
uint8_t *buffer,
|
||||
|
@ -639,6 +653,9 @@ private:
|
|||
PalSigningMonitor &_signing_monitor;
|
||||
|
||||
SecurityDb *_db;
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
PrivateAddressController &_private_address_controller;
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
/* OOB data */
|
||||
address_t _oob_local_address;
|
||||
|
|
|
@ -652,6 +652,30 @@ struct direct_address_type_t : SafeEnum<direct_address_type_t, uint8_t> {
|
|||
|
||||
typedef ble::clock_accuracy_t clock_accuracy_t;
|
||||
|
||||
/**
|
||||
* Define the privacy mode of a peer.
|
||||
*/
|
||||
struct privacy_mode_t : SafeEnum<privacy_mode_t, uint8_t> {
|
||||
enum type {
|
||||
/**
|
||||
* In Network mode, an observer or peripheral does not accept advertising
|
||||
* packets containing the identity address of peer devices that have
|
||||
* distributed their IRK
|
||||
*/
|
||||
NETWORK,
|
||||
|
||||
/**
|
||||
* In this mode, the device is only concerned about its own privacy.
|
||||
* This mode should only be used when the Resolvable Private Address
|
||||
* Only characteristic is not present in the GAP service of the peer
|
||||
* device.
|
||||
*/
|
||||
DEVICE
|
||||
};
|
||||
|
||||
privacy_mode_t(type value) : SafeEnum<privacy_mode_t, uint8_t>(value) {}
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif /* BLE_PAL_GAP_TYPES_H_ */
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "platform/Callback.h"
|
||||
|
||||
#include "ble/common/BLERoles.h"
|
||||
#include "source/pal/GapTypes.h"
|
||||
#include "source/pal/GapEvents.h"
|
||||
#include "ble/common/blecommon.h"
|
||||
|
@ -29,6 +30,8 @@ namespace ble {
|
|||
|
||||
struct PalGapEventHandler {
|
||||
public:
|
||||
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
/**
|
||||
* @copydoc PalGap::EventHandler::onReadPhy
|
||||
*/
|
||||
|
@ -38,6 +41,7 @@ public:
|
|||
ble::phy_t tx_phy,
|
||||
ble::phy_t rx_phy
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
/**
|
||||
* @copydoc PalGap::EventHandler::onDataLengthChange
|
||||
|
@ -48,6 +52,7 @@ public:
|
|||
uint16_t rx_size
|
||||
) = 0;
|
||||
|
||||
#if BLE_FEATURE_PHY_MANAGEMENT
|
||||
/**
|
||||
* @copydoc PalGap::EventHandler::onPhyUpdateComplete
|
||||
*/
|
||||
|
@ -57,60 +62,10 @@ public:
|
|||
ble::phy_t tx_phy,
|
||||
ble::phy_t rx_phy
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_PHY_MANAGEMENT
|
||||
|
||||
/**
|
||||
* Should be invoked by the PalGap implementation when an enhanced
|
||||
* connection complete event happens.
|
||||
*
|
||||
* @param status hci_error_code::SUCCESS in case of success or an error
|
||||
* code.
|
||||
*
|
||||
* @param connection_handle The handle of the connection created.
|
||||
*
|
||||
* @param own_role Indicate if the local device operates as slave or
|
||||
* master.
|
||||
*
|
||||
* @param peer_address_type Type of address of the peer.
|
||||
*
|
||||
* @param peer_address Address of the peer connected.
|
||||
*
|
||||
* @param local_resolvable_private_address Resolvable private address
|
||||
* being used by the controller. If not applicable, the address is full
|
||||
* of zeroes.
|
||||
*
|
||||
* @param peer_resolvable_private_address Resolvable private address
|
||||
* being used by the peer. If not applicable, the address is full of
|
||||
* zeroes.
|
||||
*
|
||||
* @param connection_interval Interval between two connection events.
|
||||
* Unit is 1.25ms.
|
||||
*
|
||||
* @param connection_latency Slave latency for the connection in number
|
||||
* of connection events.
|
||||
*
|
||||
* @param supervision_timeout Connection supervision timeout. Unit is
|
||||
* 10ms.
|
||||
*
|
||||
* @param master_clock_accuracy This parameter is only valid for a slave.
|
||||
* On a master it must be set to 0x00.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.7.65.10 LE enhanced connection
|
||||
* complete event.
|
||||
*/
|
||||
virtual void on_enhanced_connection_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
connection_role_t own_role,
|
||||
connection_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address,
|
||||
const address_t &local_resolvable_private_address,
|
||||
const address_t &peer_resolvable_private_address,
|
||||
uint16_t connection_interval,
|
||||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout,
|
||||
clock_accuracy_t master_clock_accuracy
|
||||
) = 0;
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
#if BLE_ROLE_OBSERVER
|
||||
/** Called on advertising report event.
|
||||
*
|
||||
* @param event_type Type of advertising used.
|
||||
|
@ -145,7 +100,11 @@ public:
|
|||
uint8_t data_length,
|
||||
const uint8_t *data_size
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
#if BLE_ROLE_OBSERVER
|
||||
/** Called on advertising sync event.
|
||||
*
|
||||
* @param error SUCCESS if synchronisation was achieved.
|
||||
|
@ -193,10 +152,41 @@ public:
|
|||
virtual void on_periodic_advertising_sync_loss(
|
||||
sync_handle_t sync_handle
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_PERIODIC_ADVERTISING
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_ROLE_OBSERVER
|
||||
/**
|
||||
* Called when scanning start
|
||||
*/
|
||||
virtual void on_scan_started(bool success) = 0;
|
||||
|
||||
/**
|
||||
* Called when scanning stop
|
||||
*/
|
||||
virtual void on_scan_stopped(bool success) = 0;
|
||||
|
||||
|
||||
/** Called when scanning times out.
|
||||
*/
|
||||
virtual void on_scan_timeout( ) = 0;
|
||||
#endif // BLE_ROLE_OBSERVER
|
||||
|
||||
#if BLE_ROLE_BROADCASTER
|
||||
/**
|
||||
* Called when legacy advertising has been effectively started.
|
||||
*/
|
||||
virtual void on_legacy_advertising_started() = 0;
|
||||
|
||||
/**
|
||||
* Called when legacy advertising has been stopped.
|
||||
*/
|
||||
virtual void on_legacy_advertising_stopped() = 0;
|
||||
|
||||
/**
|
||||
* Called when extended advertising has been started.
|
||||
*/
|
||||
virtual void on_advertising_set_started(const mbed::Span<const uint8_t>& handles) = 0;
|
||||
|
||||
/** Called when advertising set stops advertising.
|
||||
*
|
||||
|
@ -223,7 +213,9 @@ public:
|
|||
connection_peer_address_type_t scanner_address_type,
|
||||
const address_t &address
|
||||
) = 0;
|
||||
#endif // BLE_ROLE_BROADCASTER
|
||||
|
||||
#if BLE_FEATURE_CONNECTABLE
|
||||
virtual void on_connection_update_complete(
|
||||
hci_error_code_t status,
|
||||
connection_handle_t connection_handle,
|
||||
|
@ -239,6 +231,7 @@ public:
|
|||
uint16_t connection_latency,
|
||||
uint16_t supervision_timeout
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_CONNECTABLE
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -402,6 +395,7 @@ public:
|
|||
advertising_filter_policy_t advertising_filter_policy
|
||||
) = 0;
|
||||
|
||||
#if BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
/**
|
||||
* Define the advertising parameters of an advertising set.
|
||||
*
|
||||
|
@ -478,6 +472,7 @@ public:
|
|||
uint8_t advertising_sid,
|
||||
bool scan_request_notification
|
||||
) = 0;
|
||||
#endif // BLE_FEATURE_EXTENDED_ADVERTISING
|
||||
|
||||
/**
|
||||
* Configure periodic advertising parameters of an advertising set.
|
||||
|
@ -1549,27 +1544,6 @@ public:
|
|||
local_disconnection_reason_t disconnection_reason
|
||||
) = 0;
|
||||
|
||||
/** Check if privacy feature is supported by implementation
|
||||
*
|
||||
* @return true if privacy is supported, false otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature.
|
||||
*/
|
||||
virtual bool is_privacy_supported() = 0;
|
||||
|
||||
/** Enable or disable private addresses resolution
|
||||
*
|
||||
* @param enable whether to enable private addresses resolution
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable command.
|
||||
*/
|
||||
virtual ble_error_t set_address_resolution(
|
||||
bool enable
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Checked support for a feature in the link controller.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,251 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2020 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H
|
||||
#define BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
|
||||
#include "ble/common/BLETypes.h"
|
||||
#include "ble/common/blecommon.h"
|
||||
#include "GapTypes.h"
|
||||
|
||||
namespace ble {
|
||||
|
||||
/**
|
||||
* Control the controller resolution list, resolve private addresses and generate
|
||||
* new ones.
|
||||
*/
|
||||
struct PalPrivateAddressController {
|
||||
struct EventHandler {
|
||||
#if BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
/** Called when the address resolution request has completed.
|
||||
*
|
||||
* @param success true if the address has been resolved and false otherwise.
|
||||
*/
|
||||
virtual void on_private_address_resolved(bool success) = 0;
|
||||
#endif // BLE_GAP_HOST_BASED_PRIVATE_ADDRESS_RESOLUTION
|
||||
|
||||
/** Called when the resolvable private address request has completed.
|
||||
*
|
||||
* @param rpa The address generated. In case of failure, the address is
|
||||
* equal to an invalid address (default value from address_t).
|
||||
*/
|
||||
virtual void on_resolvable_private_address_generated(const address_t &rpa) = 0;
|
||||
|
||||
/**
|
||||
* Called when a new item has been added or removed to the resolving list
|
||||
* or if the resolving list has been cleared.
|
||||
*/
|
||||
virtual void on_resolving_list_action_complete() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the address registry module
|
||||
* @return BLE_ERROR_NONE in case of success.
|
||||
*/
|
||||
virtual ble_error_t initialize() = 0;
|
||||
|
||||
/**
|
||||
* Terminate the address registry module
|
||||
* @return BLE_ERROR_NONE in case of success.
|
||||
*/
|
||||
virtual ble_error_t terminate() = 0;
|
||||
|
||||
/** Generate a new resolvable private address from an IRK
|
||||
*
|
||||
* The completion of the request is signaled by the stack with a call to
|
||||
* PalPrivateAddressController::on_resolvable_private_address_generated.
|
||||
*
|
||||
* @param local_irk The IRK to use to generate the address.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note Addresses are generated one at a time, this function should not be
|
||||
* called while an address is being generated.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.2 Private Device Address Generation
|
||||
*/
|
||||
virtual ble_error_t generate_resolvable_private_address(const irk_t& local_irk) = 0;
|
||||
|
||||
/** Generate a new non-resolvable private address
|
||||
*
|
||||
* @return The address generated.
|
||||
*
|
||||
* @note The address generated might be invalid (all zeros).
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.2 Private Device Address Generation
|
||||
*/
|
||||
virtual address_t generate_non_resolvable_private_address() = 0;
|
||||
|
||||
/** Attempt to resolve a resolvable private address received with an IRK.
|
||||
*
|
||||
* The completion of the request is signaled by the stack with a call to
|
||||
* PalGapEventHandler::on_private_address_resolved.
|
||||
*
|
||||
* @param address The address to resole
|
||||
* @param irk The IRK used for the resolution of the address.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note Addresses are resolved one at a time, this function should not be
|
||||
* called while an address is being resolved.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 6 PartB: 1.3.2.3 Private Device Address Resolution
|
||||
*/
|
||||
virtual ble_error_t resolve_private_address(
|
||||
const address_t &address,
|
||||
const irk_t& irk
|
||||
) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// LL resolution and generation management
|
||||
//
|
||||
|
||||
/** Check if privacy feature is supported by LL implementation
|
||||
*
|
||||
* @return true if privacy is supported, false otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 3 Part C: 10.7 Privacy feature.
|
||||
*/
|
||||
virtual bool is_ll_privacy_supported() = 0;
|
||||
|
||||
/** Enable or disable private addresses resolution
|
||||
*
|
||||
* @param enable whether to enable private addresses resolution
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.44 LE Set Address Resolution Enable command.
|
||||
*/
|
||||
virtual ble_error_t set_ll_address_resolution(
|
||||
bool enable
|
||||
) = 0;
|
||||
|
||||
/** Set the timeout for LL resolvable private address rotation.
|
||||
*
|
||||
* @param timeout The timeout after which the resolvable private address in
|
||||
* the controller is changed.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.45 LE Set Resolvable Private Address Timeout Command
|
||||
*/
|
||||
virtual ble_error_t set_ll_resolvable_private_address_timeout(resolvable_address_timeout_t timeout) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Resolving list management
|
||||
//
|
||||
|
||||
/** Return the resolving list capacity
|
||||
*
|
||||
* @return A positive number if LL privacy is supported, 0 if not.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.41 LE Read Resolving List Size Command.
|
||||
*/
|
||||
virtual uint8_t read_resolving_list_capacity() = 0;
|
||||
|
||||
/** Add a device definition into the resolving list.
|
||||
*
|
||||
* @param peer_address_type The type of the identity address received from the
|
||||
* peer during bonding.
|
||||
* @param peer_identity_address The identity address of the peer received
|
||||
* during bonding.
|
||||
* @param peer_irk The irk of the peer.
|
||||
* @param local_irk The irk sent to the peer during bonding.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: Cannot be used if address translation is enabled and the device is
|
||||
* advertising/scanning or initiating.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.38 LE Add Device To Resolving List Command
|
||||
*/
|
||||
virtual ble_error_t add_device_to_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t& peer_irk,
|
||||
const irk_t& local_irk
|
||||
) = 0;
|
||||
|
||||
/** Remove a device definition from the resolving list.
|
||||
*
|
||||
* @param peer_address_type The type of the identity address received from the
|
||||
* peer during bonding.
|
||||
* @param peer_identity_address The identity address of the peer received
|
||||
* during bonding.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: Cannot be used if address translation is enabled and the device is
|
||||
* advertising/scanning or initiating.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.39 LE Remove Device From Resolving List Command
|
||||
*/
|
||||
virtual ble_error_t remove_device_from_resolving_list(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) = 0;
|
||||
|
||||
/** Remove all entries from the resolving list.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: Cannot be used if address translation is enabled and the device is
|
||||
* advertising/scanning or initiating.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.40 LE Clear Resolving List Command
|
||||
*/
|
||||
virtual ble_error_t clear_resolving_list() = 0;
|
||||
|
||||
/** Set the privacy mode (for LL controllers)
|
||||
*
|
||||
* @param peer_address_type The identity address type of the peer
|
||||
* @param peer_address The identity address of the peer
|
||||
* @param privacy_mode whether network or device privacy should be used for
|
||||
* the peer.
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the request has been successfully sent or the
|
||||
* appropriate error otherwise.
|
||||
*
|
||||
* @note: See Bluetooth 5 Vol 2 PartE: 7.8.77 LE Set Privacy Mode Command
|
||||
*/
|
||||
virtual ble_error_t set_peer_privacy_mode(
|
||||
target_peer_address_type_t peer_address_type,
|
||||
const address_t &peer_address,
|
||||
privacy_mode_t privacy_mode
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the event handler receiving events from this instance.
|
||||
* @param handler The handler to use when an event happen.
|
||||
*/
|
||||
virtual void set_event_handler(EventHandler *handler) = 0;
|
||||
};
|
||||
|
||||
} // namespace ble
|
||||
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
#endif //BLE_PAL_PRIVATE_ADDRESS_CONTROLLER_H
|
|
@ -559,56 +559,6 @@ public:
|
|||
*/
|
||||
virtual ble_error_t reset() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Resolving list management
|
||||
//
|
||||
/**
|
||||
* Return the number of address translation entries that can be stored by the
|
||||
* subsystem.
|
||||
*
|
||||
* @warning: The number of entries is considered fixed.
|
||||
*
|
||||
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.41
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||
*/
|
||||
virtual uint8_t read_resolving_list_capacity() = 0;
|
||||
|
||||
/**
|
||||
* Add a device definition into the resolving list of the LE subsystem.
|
||||
*
|
||||
* @param[in] peer_identity_address_type public/private indicator
|
||||
* @param[in] peer_identity_address address of the device whose entry is to be added
|
||||
* @param[in] peer_irk peer identity resolving key
|
||||
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.38
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||
*/
|
||||
virtual ble_error_t add_device_to_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address,
|
||||
const irk_t &peer_irk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Add a device definition from the resolving list of the LE subsystem.
|
||||
*
|
||||
* @param[in] peer_identity_address_type public/private indicator
|
||||
* @param[in] peer_identity_address address of the device whose entry is to be removed
|
||||
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.39
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||
*/
|
||||
virtual ble_error_t remove_device_from_resolving_list(
|
||||
advertising_peer_address_type_t peer_identity_address_type,
|
||||
const address_t &peer_identity_address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Remove all devices from the resolving list.
|
||||
*
|
||||
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.40
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||
*/
|
||||
virtual ble_error_t clear_resolving_list() = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pairing
|
||||
//
|
||||
|
@ -803,28 +753,6 @@ public:
|
|||
encryption_block_t &data
|
||||
) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Privacy
|
||||
//
|
||||
|
||||
virtual ble_error_t set_private_address_timeout(
|
||||
uint16_t timeout_in_seconds
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the identity address used by the controller
|
||||
*
|
||||
* @param address Will contain the address retrieved.
|
||||
* @param public_address will be true if the address is public and false
|
||||
* otherwise.
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating the reason
|
||||
* of the failure
|
||||
*/
|
||||
virtual ble_error_t get_identity_address(
|
||||
address_t& address,
|
||||
bool& public_address
|
||||
) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
//
|
||||
|
@ -864,6 +792,18 @@ public:
|
|||
virtual ble_error_t set_irk(
|
||||
const irk_t &irk
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the local identity address.
|
||||
*
|
||||
* @param[in] address identity address of the device
|
||||
* @param[in] public_address true if a public address is used and false otherwise.
|
||||
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||
*/
|
||||
virtual ble_error_t set_identity_address(
|
||||
const address_t &address, bool public_address
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
* Set the local CSRK.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue