mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #48 from paul-szczepanek-arm/sm-init-error
allow changing database at runtime and add checking for initialisationpull/6932/head
commit
4e3a9ffabb
|
@ -441,7 +441,7 @@ public:
|
|||
* support out-of-band exchanges of security data.
|
||||
* @param[in] passkey To specify a static passkey.
|
||||
* @param[in] signing Generate and distribute signing key during pairing
|
||||
* @param[in] dbPath Path to the folder used to store keys in the filesystem,
|
||||
* @param[in] dbPath Path to the file used to store keys in the filesystem,
|
||||
* if NULL keys will be only stored in memory
|
||||
*
|
||||
*
|
||||
|
@ -452,17 +452,33 @@ public:
|
|||
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
|
||||
const Passkey_t passkey = NULL,
|
||||
bool signing = true,
|
||||
const char *dbPath = NULL) {
|
||||
const char *dbFilepath = NULL) {
|
||||
/* Avoid compiler warnings about unused variables. */
|
||||
(void)enableBonding;
|
||||
(void)requireMITM;
|
||||
(void)iocaps;
|
||||
(void)passkey;
|
||||
(void)dbPath;
|
||||
(void)dbFilepath;
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the file used for the security database. If path is invalid or a NULL is passed
|
||||
* keys will only be stored in memory.
|
||||
*
|
||||
* @note This operation is only allowed with no active connections.
|
||||
*
|
||||
* @param[in] dbPath Path to the file used to store keys in the filesystem,
|
||||
* if NULL keys will be only stored in memory
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
virtual ble_error_t setDatabaseFilepath(const char *dbFilepath = NULL) {
|
||||
(void)dbFilepath;
|
||||
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all registered onShutdown callbacks that the SecurityManager is
|
||||
* about to be shutdown and clear all SecurityManager state of the
|
||||
|
|
|
@ -53,6 +53,8 @@ public:
|
|||
const char* db_path = NULL
|
||||
);
|
||||
|
||||
virtual ble_error_t setDatabaseFilepath(const char *db_path = NULL);
|
||||
|
||||
virtual ble_error_t reset();
|
||||
|
||||
virtual ble_error_t preserveBondingStateOnReset(
|
||||
|
@ -263,6 +265,22 @@ public:
|
|||
//
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Initialise the database, if database already exists it will close it and open the new one.
|
||||
*
|
||||
* @param db_path path to file to store secure db
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t init_database(const char *db_path = NULL);
|
||||
|
||||
/**
|
||||
* Generate identity list based on the database of IRK and apply it to the resolving list.
|
||||
*
|
||||
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
|
||||
*/
|
||||
ble_error_t init_resolving_list();
|
||||
|
||||
/**
|
||||
* Generate the CSRK if needed.
|
||||
*
|
||||
|
|
|
@ -42,30 +42,18 @@ ble_error_t GenericSecurityManager::init(
|
|||
bool signing,
|
||||
const char* db_path
|
||||
) {
|
||||
ble_error_t result = _pal.initialize();
|
||||
|
||||
ble_error_t err = _pal.initialize();
|
||||
if (err) {
|
||||
return err;
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_db) {
|
||||
delete _db;
|
||||
result = init_database(db_path);
|
||||
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
FILE* db_file = FileSecurityDb::open_db_file(db_path);
|
||||
|
||||
if (db_file) {
|
||||
_db = new (std::nothrow) FileSecurityDb(db_file);
|
||||
} else {
|
||||
_db = new (std::nothrow) MemorySecurityDb();
|
||||
}
|
||||
|
||||
if (!_db) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
_db->restore();
|
||||
|
||||
_pal.set_io_capability((io_capability_t::type) iocaps);
|
||||
|
||||
if (passkey) {
|
||||
|
@ -96,25 +84,38 @@ ble_error_t GenericSecurityManager::init(
|
|||
_signing_monitor.set_signing_event_handler(this);
|
||||
_pal.set_event_handler(this);
|
||||
|
||||
uint8_t resolving_list_capacity = _pal.read_resolving_list_capacity();
|
||||
SecurityEntryIdentity_t* identity_list_p =
|
||||
new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
|
||||
result = init_resolving_list();
|
||||
|
||||
if (identity_list_p) {
|
||||
ArrayView<SecurityEntryIdentity_t> identity_list(
|
||||
identity_list_p,
|
||||
resolving_list_capacity
|
||||
);
|
||||
|
||||
_db->get_identity_list(
|
||||
mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved),
|
||||
identity_list
|
||||
);
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
delete _db;
|
||||
return result;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::setDatabaseFilepath(
|
||||
const char *db_path
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
|
||||
/* operation only allowed with no connections active */
|
||||
for (size_t i = 0; i < MAX_CONTROL_BLOCKS; i++) {
|
||||
if (_control_blocks[i].connected) {
|
||||
return BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t result = init_database(db_path);
|
||||
if (result != BLE_ERROR_NONE) {
|
||||
return result;
|
||||
}
|
||||
|
||||
init_resolving_list();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::reset(void) {
|
||||
_pal.reset();
|
||||
SecurityManager::reset();
|
||||
|
@ -123,7 +124,7 @@ ble_error_t GenericSecurityManager::reset(void) {
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
_db->set_restore(enabled);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -133,13 +134,13 @@ ble_error_t GenericSecurityManager::preserveBondingStateOnReset(bool enabled) {
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::purgeAllBondingState(void) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
_db->clear_entries();
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
if (eventHandler) {
|
||||
_db->generate_whitelist_from_bond_table(
|
||||
mbed::callback(eventHandler, &::SecurityManager::EventHandler::whitelistFromBondTable),
|
||||
|
@ -154,6 +155,7 @@ ble_error_t GenericSecurityManager::generateWhitelistFromBondTable(Gap::Whitelis
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connection) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -206,6 +208,7 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t connection) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -263,10 +266,12 @@ ble_error_t GenericSecurityManager::acceptPairingRequest(connection_handle_t con
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::cancelPairingRequest(connection_handle_t connection) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.cancel_pairing(connection, pairing_failure_t::UNSPECIFIED_REASON);
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::setPairingRequestAuthorisation(bool required) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
_pairing_authorisation_required = required;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -289,10 +294,12 @@ ble_error_t GenericSecurityManager::getSecureConnectionsSupport(bool *enabled) {
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::setIoCapability(SecurityIOCapabilities_t iocaps) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_io_capability((io_capability_t::type) iocaps);
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::setDisplayPasskey(const Passkey_t passkey) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_display_passkey(PasskeyAscii::to_num(passkey));
|
||||
}
|
||||
|
||||
|
@ -300,6 +307,7 @@ ble_error_t GenericSecurityManager::setAuthenticationTimeout(
|
|||
connection_handle_t connection,
|
||||
uint32_t timeout_in_ms
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_authentication_timeout(connection, timeout_in_ms / 10);
|
||||
}
|
||||
|
||||
|
@ -307,6 +315,7 @@ ble_error_t GenericSecurityManager::getAuthenticationTimeout(
|
|||
connection_handle_t connection,
|
||||
uint32_t *timeout_in_ms
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
uint16_t timeout_in_10ms;
|
||||
ble_error_t status = _pal.get_authentication_timeout(connection, timeout_in_10ms);
|
||||
*timeout_in_ms = 10 * timeout_in_10ms;
|
||||
|
@ -317,6 +326,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity(
|
|||
connection_handle_t connection,
|
||||
SecurityMode_t securityMode
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -348,6 +358,7 @@ ble_error_t GenericSecurityManager::setLinkSecurity(
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::setKeypressNotification(bool enabled) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
_default_authentication.set_keypress_notification(enabled);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
@ -356,7 +367,7 @@ ble_error_t GenericSecurityManager::enableSigning(
|
|||
connection_handle_t connection,
|
||||
bool enabled
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -406,7 +417,7 @@ ble_error_t GenericSecurityManager::getLinkEncryption(
|
|||
connection_handle_t connection,
|
||||
link_encryption_t *encryption
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -440,7 +451,7 @@ ble_error_t GenericSecurityManager::setLinkEncryption(
|
|||
connection_handle_t connection,
|
||||
link_encryption_t encryption
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -511,7 +522,7 @@ ble_error_t GenericSecurityManager::getEncryptionKeySize(
|
|||
connection_handle_t connection,
|
||||
uint8_t *size
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -530,6 +541,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
|
|||
uint8_t minimumByteSize,
|
||||
uint8_t maximumByteSize
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_encryption_key_requirements(minimumByteSize, maximumByteSize);
|
||||
}
|
||||
|
||||
|
@ -538,7 +550,7 @@ ble_error_t GenericSecurityManager::setEncryptionKeyRequirements(
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection, bool authenticated) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -576,6 +588,7 @@ ble_error_t GenericSecurityManager::getSigningKey(connection_handle_t connection
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in_seconds) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.set_private_address_timeout(timeout_in_seconds);
|
||||
}
|
||||
|
||||
|
@ -584,7 +597,7 @@ ble_error_t GenericSecurityManager::setPrivateAddressTimeout(uint16_t timeout_in
|
|||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -619,6 +632,7 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co
|
|||
ble_error_t GenericSecurityManager::generateOOB(
|
||||
const address_t *address
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
/* legacy pairing */
|
||||
ble_error_t status = get_random_data(_oob_temporary_key.data(), 16);
|
||||
|
||||
|
@ -658,6 +672,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage(
|
|||
bool useOOB,
|
||||
bool OOBProvidesMITM
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -677,6 +692,7 @@ ble_error_t GenericSecurityManager::confirmationEntered(
|
|||
connection_handle_t connection,
|
||||
bool confirmation
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.confirmation_entered(connection, confirmation);
|
||||
}
|
||||
|
||||
|
@ -684,6 +700,7 @@ ble_error_t GenericSecurityManager::passkeyEntered(
|
|||
connection_handle_t connection,
|
||||
Passkey_t passkey
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.passkey_request_reply(
|
||||
connection,
|
||||
PasskeyAscii::to_num(passkey)
|
||||
|
@ -694,6 +711,7 @@ ble_error_t GenericSecurityManager::sendKeypressNotification(
|
|||
connection_handle_t connection,
|
||||
Keypress_t keypress
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
return _pal.send_keypress_notification(connection, keypress);
|
||||
}
|
||||
|
||||
|
@ -701,7 +719,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived(
|
|||
const address_t *address,
|
||||
const oob_tk_t *tk
|
||||
) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
if (address && tk) {
|
||||
ControlBlock_t *cb = get_control_block(*address);
|
||||
if (!cb) {
|
||||
|
@ -736,6 +754,7 @@ ble_error_t GenericSecurityManager::oobReceived(
|
|||
const oob_lesc_value_t *random,
|
||||
const oob_confirm_t *confirm
|
||||
) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
if (address && random && confirm) {
|
||||
_oob_peer_address = *address;
|
||||
_oob_peer_random = *random;
|
||||
|
@ -750,8 +769,55 @@ ble_error_t GenericSecurityManager::oobReceived(
|
|||
// Helper functions
|
||||
//
|
||||
|
||||
ble_error_t GenericSecurityManager::init_database(
|
||||
const char *db_path
|
||||
) {
|
||||
delete _db;
|
||||
|
||||
FILE* db_file = FileSecurityDb::open_db_file(db_path);
|
||||
|
||||
if (db_file) {
|
||||
_db = new (std::nothrow) FileSecurityDb(db_file);
|
||||
} else {
|
||||
_db = new (std::nothrow) MemorySecurityDb();
|
||||
}
|
||||
|
||||
if (!_db) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
_db->restore();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::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();
|
||||
SecurityEntryIdentity_t* identity_list_p =
|
||||
new (std::nothrow) SecurityEntryIdentity_t[resolving_list_capacity];
|
||||
|
||||
if (identity_list_p) {
|
||||
ArrayView<SecurityEntryIdentity_t> identity_list(
|
||||
identity_list_p,
|
||||
resolving_list_capacity
|
||||
);
|
||||
|
||||
_db->get_identity_list(
|
||||
mbed::callback(this, &GenericSecurityManager::on_identity_list_retrieved),
|
||||
identity_list
|
||||
);
|
||||
} else {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::init_signing() {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
const csrk_t *pcsrk = _db->get_local_csrk();
|
||||
sign_count_t local_sign_counter = _db->get_local_sign_counter();
|
||||
|
||||
|
@ -791,6 +857,7 @@ ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t connection) {
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
@ -801,7 +868,7 @@ ble_error_t GenericSecurityManager::slave_security_request(connection_handle_t c
|
|||
}
|
||||
|
||||
ble_error_t GenericSecurityManager::enable_encryption(connection_handle_t connection) {
|
||||
MBED_ASSERT(_db);
|
||||
if (!_db) return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
ControlBlock_t *cb = get_control_block(connection);
|
||||
if (!cb) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
|
Loading…
Reference in New Issue