mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #13037 from paul-szczepanek-arm/ble-sm-fix
BLE: Fix privacy and signing handling in Security Managerpull/13095/head
commit
2466411b83
|
@ -285,6 +285,22 @@ public:
|
|||
(void)result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that a peer address has been saved by the security manager or if we are
|
||||
* bonded to the peer the identity has been retrieved from the database on connection.
|
||||
*
|
||||
* @param[in] connectionHandle Connection handle.
|
||||
* @param[in] peer_address Peer address that has been saved by the security database, NULL it not found.
|
||||
* @param[in] address_is_public Address type, true if public. Invalid if peer_address NULL.
|
||||
*/
|
||||
virtual void peerIdentity(ble::connection_handle_t connectionHandle,
|
||||
const address_t *peer_address,
|
||||
bool address_is_public) {
|
||||
(void)connectionHandle;
|
||||
(void)peer_address;
|
||||
(void)address_is_public;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Security
|
||||
//
|
||||
|
@ -561,6 +577,14 @@ public:
|
|||
*/
|
||||
ble_error_t setPairingRequestAuthorisation(bool required = true);
|
||||
|
||||
/**
|
||||
* Retrieve identity address for the peer on the given connection.
|
||||
*
|
||||
* @param[in] connectionHandle Handle to identify the connection.
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t getPeerIdentity(ble::connection_handle_t connectionHandle);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Feature support
|
||||
//
|
||||
|
@ -899,6 +923,10 @@ protected:
|
|||
ble::connection_handle_t connectionHandle
|
||||
);
|
||||
|
||||
ble_error_t getPeerIdentity_(
|
||||
ble::connection_handle_t connectionHandle
|
||||
);
|
||||
|
||||
ble_error_t setPairingRequestAuthorisation_(
|
||||
bool required
|
||||
);
|
||||
|
|
|
@ -34,8 +34,6 @@ private:
|
|||
size_t file_offset;
|
||||
};
|
||||
|
||||
static const size_t MAX_ENTRIES = 5;
|
||||
|
||||
static entry_t* as_entry(entry_handle_t db_handle) {
|
||||
return reinterpret_cast<entry_t*>(db_handle);
|
||||
}
|
||||
|
@ -118,6 +116,21 @@ public:
|
|||
sign_count_t sign_counter
|
||||
);
|
||||
|
||||
/* local csrk and identity */
|
||||
|
||||
virtual void set_local_csrk(
|
||||
const csrk_t &csrk
|
||||
);
|
||||
|
||||
virtual void set_local_identity(
|
||||
const irk_t &irk,
|
||||
const address_t &identity_address,
|
||||
bool public_address
|
||||
);
|
||||
|
||||
/* I am not overriding set_local_sign_counter to avoid constant filesystem writes,
|
||||
* instead this is synced by sync (which is called on disconnection) */
|
||||
|
||||
/* saving and loading from nvm */
|
||||
|
||||
virtual void restore();
|
||||
|
@ -146,7 +159,7 @@ private:
|
|||
static FILE* erase_db_file(FILE* db_file);
|
||||
|
||||
private:
|
||||
entry_t _entries[MAX_ENTRIES];
|
||||
entry_t _entries[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
||||
FILE *_db_file;
|
||||
uint8_t _buffer[sizeof(SecurityEntryKeys_t)];
|
||||
};
|
||||
|
|
|
@ -124,6 +124,10 @@ public:
|
|||
bool required = true
|
||||
);
|
||||
|
||||
ble_error_t getPeerIdentity_(
|
||||
connection_handle_t connection
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Feature support
|
||||
//
|
||||
|
@ -321,6 +325,13 @@ private:
|
|||
*/
|
||||
ble_error_t init_signing();
|
||||
|
||||
/**
|
||||
* Generate the IRK if needed.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t init_identity();
|
||||
|
||||
/**
|
||||
* Fills the buffer with the specified number of bytes of random data
|
||||
* produced by the link controller
|
||||
|
|
|
@ -34,8 +34,6 @@ private:
|
|||
SecurityEntrySigning_t peer_signing;
|
||||
};
|
||||
|
||||
static const size_t MAX_ENTRIES = 5;
|
||||
|
||||
static entry_t* as_entry(entry_handle_t db_handle)
|
||||
{
|
||||
return reinterpret_cast<entry_t*>(db_handle);
|
||||
|
@ -150,11 +148,11 @@ public:
|
|||
|
||||
private:
|
||||
virtual uint8_t get_entry_count() {
|
||||
return MAX_ENTRIES;
|
||||
return BLE_SECURITY_DATABASE_MAX_ENTRIES;
|
||||
}
|
||||
|
||||
virtual SecurityDistributionFlags_t* get_entry_handle_by_index(uint8_t index) {
|
||||
if (index < MAX_ENTRIES) {
|
||||
if (index < BLE_SECURITY_DATABASE_MAX_ENTRIES) {
|
||||
return &_entries[index].flags;
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -187,7 +185,7 @@ private:
|
|||
};
|
||||
|
||||
private:
|
||||
entry_t _entries[MAX_ENTRIES];
|
||||
entry_t _entries[BLE_SECURITY_DATABASE_MAX_ENTRIES];
|
||||
};
|
||||
|
||||
} /* namespace pal */
|
||||
|
|
|
@ -425,6 +425,31 @@ public:
|
|||
_local_sign_counter = sign_counter;
|
||||
}
|
||||
|
||||
/* local identity */
|
||||
/**
|
||||
* Update the local identity.
|
||||
*
|
||||
* @param[in] csrk new CSRK value
|
||||
*/
|
||||
virtual void set_local_identity(
|
||||
const irk_t &irk,
|
||||
const address_t &identity_address,
|
||||
bool public_address
|
||||
) {
|
||||
_local_identity.irk = irk;
|
||||
_local_identity.identity_address = identity_address;
|
||||
_local_identity.identity_address_is_public = public_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return local irk.
|
||||
*
|
||||
* @return irk
|
||||
*/
|
||||
virtual irk_t get_local_irk() {
|
||||
return _local_identity.irk;
|
||||
}
|
||||
|
||||
/* list management */
|
||||
|
||||
/**
|
||||
|
@ -592,6 +617,21 @@ public:
|
|||
continue;
|
||||
}
|
||||
|
||||
// Add the connection address
|
||||
whitelist->addresses[whitelist->size].address = flags->peer_address.data();
|
||||
|
||||
if (flags->peer_address_is_public) {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::PUBLIC;
|
||||
} else {
|
||||
whitelist->addresses[whitelist->size].type = peer_address_type_t::RANDOM;
|
||||
}
|
||||
|
||||
whitelist->size++;
|
||||
if (whitelist->size == whitelist->capacity) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Add the identity address
|
||||
SecurityEntryIdentity_t* identity = read_in_entry_peer_identity(db_handle);
|
||||
if (!identity) {
|
||||
continue;
|
||||
|
|
|
@ -964,7 +964,23 @@ public:
|
|||
ble_error_t set_private_address_timeout(
|
||||
uint16_t timeout_in_seconds
|
||||
) {
|
||||
return impl()->set_private_address_timeout(timeout_in_seconds);
|
||||
return impl()->set_private_address_timeout_(timeout_in_seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
ble_error_t get_identity_address(
|
||||
address_t& address,
|
||||
bool& public_address
|
||||
) {
|
||||
return impl()->get_identity_address_(address, public_address);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -71,6 +71,11 @@
|
|||
"help": "Include periodic advertising support, depends on the extended advertising feature.",
|
||||
"value": true,
|
||||
"macro_name": "BLE_FEATURE_PERIODIC_ADVERTISING"
|
||||
},
|
||||
"ble-security-database-max-entries": {
|
||||
"help": "How many entries can be stored in the db, depends on security manager.",
|
||||
"value": 5,
|
||||
"macro_name": "BLE_SECURITY_DATABASE_MAX_ENTRIES"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ const uint16_t DB_VERSION = 1;
|
|||
)
|
||||
|
||||
#define DB_SIZE_STORES \
|
||||
(FileSecurityDb::MAX_ENTRIES * DB_SIZE_STORE)
|
||||
(BLE_SECURITY_DATABASE_MAX_ENTRIES * DB_SIZE_STORE)
|
||||
|
||||
#define DB_OFFSET_VERSION (0)
|
||||
#define DB_OFFSET_RESTORE (DB_OFFSET_VERSION + sizeof(DB_VERSION))
|
||||
|
@ -265,6 +265,22 @@ void FileSecurityDb::set_entry_peer_sign_counter(
|
|||
}
|
||||
}
|
||||
|
||||
void FileSecurityDb::set_local_csrk(
|
||||
const csrk_t &csrk
|
||||
) {
|
||||
this->SecurityDb::set_local_csrk(csrk);
|
||||
db_write(&_local_csrk, DB_OFFSET_LOCAL_CSRK);
|
||||
}
|
||||
|
||||
void FileSecurityDb::set_local_identity(
|
||||
const irk_t &irk,
|
||||
const address_t &identity_address,
|
||||
bool public_address
|
||||
) {
|
||||
this->SecurityDb::set_local_identity(irk, identity_address, public_address);
|
||||
db_write(&_local_identity, DB_OFFSET_LOCAL_IDENTITY);
|
||||
}
|
||||
|
||||
/* saving and loading from nvm */
|
||||
|
||||
void FileSecurityDb::restore() {
|
||||
|
@ -299,6 +315,7 @@ void FileSecurityDb::sync(entry_handle_t db_handle) {
|
|||
|
||||
db_write(&entry->peer_sign_counter, entry->file_offset + DB_STORE_OFFSET_PEER_SIGNING_COUNT);
|
||||
db_write(&entry->flags, entry->file_offset + DB_STORE_OFFSET_FLAGS);
|
||||
db_write(&_local_sign_counter, DB_OFFSET_LOCAL_SIGN_COUNT);
|
||||
}
|
||||
|
||||
void FileSecurityDb::set_restore(bool reload) {
|
||||
|
@ -308,11 +325,11 @@ void FileSecurityDb::set_restore(bool reload) {
|
|||
/* helper functions */
|
||||
|
||||
uint8_t FileSecurityDb::get_entry_count() {
|
||||
return MAX_ENTRIES;
|
||||
return BLE_SECURITY_DATABASE_MAX_ENTRIES;
|
||||
}
|
||||
|
||||
SecurityDistributionFlags_t* FileSecurityDb::get_entry_handle_by_index(uint8_t index) {
|
||||
if (index < MAX_ENTRIES) {
|
||||
if (index < BLE_SECURITY_DATABASE_MAX_ENTRIES) {
|
||||
return &_entries[index].flags;
|
||||
} else {
|
||||
return NULL;
|
||||
|
|
|
@ -102,13 +102,19 @@ ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::init_(
|
|||
result = init_resolving_list();
|
||||
#endif
|
||||
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
// set the local identity address and irk
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
result = init_identity();
|
||||
}
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
delete _db;
|
||||
_db = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<template<class> class TPalSecurityManager, template<class> class SigningMonitor>
|
||||
|
@ -161,7 +167,21 @@ template<template<class> class TPalSecurityManager, template<class> class Signin
|
|||
ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::purgeAllBondingState_(void) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
_db->clear_entries();
|
||||
return BLE_ERROR_NONE;
|
||||
|
||||
ble_error_t ret = BLE_ERROR_NONE;
|
||||
|
||||
#if BLE_FEATURE_SIGNING
|
||||
// generate new csrk and irk
|
||||
ret = init_signing();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
#endif // BLE_FEATURE_SIGNING
|
||||
#if BLE_FEATURE_PRIVACY
|
||||
ret = init_identity();
|
||||
#endif // BLE_FEATURE_PRIVACY
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<template<class> class TPalSecurityManager, template<class> class SigningMonitor>
|
||||
|
@ -309,6 +329,33 @@ ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::setPair
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
template<template<class> class TPalSecurityManager, template<class> class SigningMonitor>
|
||||
ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::getPeerIdentity_(connection_handle_t connection) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
if (eventHandler) {
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
_db->get_entry_identity(
|
||||
[connection,this](SecurityDb::entry_handle_t handle, const SecurityEntryIdentity_t* identity) {
|
||||
if (eventHandler) {
|
||||
eventHandler->peerIdentity(
|
||||
connection,
|
||||
identity ? &identity->identity_address : nullptr,
|
||||
identity ? identity->identity_address_is_public : false
|
||||
);
|
||||
}
|
||||
},
|
||||
cb->db_entry
|
||||
);
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Feature support
|
||||
//
|
||||
|
@ -901,6 +948,33 @@ ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::init_si
|
|||
return _pal.set_csrk(*pcsrk, local_sign_counter);
|
||||
}
|
||||
|
||||
template<template<class> class TPalSecurityManager, template<class> class SigningMonitor>
|
||||
ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::init_identity() {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
const irk_t *pirk = nullptr;
|
||||
|
||||
irk_t irk = _db->get_local_irk();
|
||||
if (irk != irk_t()) {
|
||||
pirk = &irk;
|
||||
} else {
|
||||
ble_error_t ret = get_random_data(irk.data(), irk.size());
|
||||
if (ret != BLE_ERROR_NONE) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return _pal.set_irk(*pirk);
|
||||
}
|
||||
|
||||
template<template<class> class TPalSecurityManager, template<class> class SigningMonitor>
|
||||
ble_error_t GenericSecurityManager<TPalSecurityManager, SigningMonitor>::get_random_data(uint8_t *buffer, size_t size) {
|
||||
byte_array_t<8> random_data;
|
||||
|
|
|
@ -212,6 +212,11 @@ public:
|
|||
*/
|
||||
ble_error_t set_private_address_timeout_(uint16_t timeout_in_seconds);
|
||||
|
||||
/**
|
||||
* @see ::ble::pal::SecurityManager::get_identity_address
|
||||
*/
|
||||
ble_error_t get_identity_address_(address_t& address, bool& public_address);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Keys
|
||||
//
|
||||
|
|
|
@ -279,6 +279,20 @@ ble_error_t CordioSecurityManager<EventHandler>::set_private_address_timeout_(
|
|||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ::ble::pal::SecurityManager::get_identity_address
|
||||
*/
|
||||
template <class EventHandler>
|
||||
ble_error_t CordioSecurityManager<EventHandler>::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
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue