Merge branch 'security-manager-dev' of https://github.com/paul-szczepanek-arm/mbed-os into sc-nordic

pull/6932/head
Vincent Coubard 2018-03-26 17:12:37 +01:00
commit 87c2045f5e
6 changed files with 248 additions and 184 deletions

View File

@ -736,7 +736,8 @@ public:
//
/**
* Enable OOB data usage during paring.
* Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will
* generate Secure Connections OOB data through oobGenerated().
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[in] useOOB If set to true, authenticate using OOB data.

View File

@ -433,12 +433,21 @@ private:
uint8_t attempt_oob:1;
uint8_t oob_mitm_protection:1;
uint8_t oob_present:1;
uint8_t legacy_pairing_oob_request_pending:1;
};
pal::SecurityManager &_pal;
pal::SecurityDb &_db;
pal::ConnectionEventMonitor &_connection_monitor;
/* OOB data */
address_t _oob_peer_address;
oob_lesc_value_t _oob_peer_random;
oob_confirm_t _oob_peer_confirm;
oob_lesc_value_t _oob_local_random;
address_t _oob_temporary_key_creator_address; /**< device which generated and sent the TK */
oob_tk_t _oob_temporary_key; /**< used for legacy pairing */
pal::AuthenticationMask _default_authentication;
pal::KeyDistribution _default_key_distribution;
@ -548,6 +557,12 @@ public:
connection_handle_t connection
);
/** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_request
*/
virtual void on_secure_connections_oob_request(
connection_handle_t connection
);
/** @copydoc ble::pal::SecurityManager::on_legacy_pairing_oob_request
*/
virtual void on_legacy_pairing_oob_request(
@ -557,7 +572,7 @@ public:
/** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated
*/
virtual void on_secure_connections_oob_generated(
const address_t &local_address,
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
);

View File

@ -367,6 +367,17 @@ public:
Keypress_t keypress
) = 0;
/**
* Request OOB data from the user application.
*
* @param[in] connection connection handle
* @note shall be followed by: pal::SecurityManager::secure_connections_oob_request_reply
* or a cancellation of the procedure.
*/
virtual void on_secure_connections_oob_request(
connection_handle_t connection
) = 0;
/**
* Request OOB data from the user application.
*
@ -381,14 +392,14 @@ public:
/**
* Send OOB data to the application for transport to the peer.
*
* @param[in] address address of the local device
* @param[in] connection connection handle
* @param[in] random random number used to generate the confirmation
* @param[in] confirm confirmation value to be use for authentication
* in secure connections pairing
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual void on_secure_connections_oob_generated(
const address_t &local_address,
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) = 0;
@ -909,7 +920,24 @@ public:
) = 0;
/**
* Reply to an oob data request received from the SecurityManagerEventHandler.
* Reply to a Secure Connections oob data request received from the SecurityManagerEventHandler.
*
* @param[in] connection connection handle
* @param[in] local_random local random number used for the last oob exchange
* @param[in] peer_random random number used to generate the confirmation on peer
* @param[in] peer_confirm confirmation value to be use for authentication
* in secure connections pairing
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t secure_connections_oob_request_reply(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random,
const oob_confirm_t &peer_confirm
) = 0;
/**
* Reply to a legacy pairing oob data request received from the SecurityManagerEventHandler.
*
* @param[in] connection connection handle
* @param[in] oob_data pointer to out of band data
@ -955,32 +983,6 @@ public:
connection_handle_t connection
) = 0;
/**
* Supply the stack with the OOB data for secure connections.
*
* @param[in] address address of the peer device this data comes from
* @param[in] random random number used to generate the confirmation
* @param[in] confirm confirmation value to be use for authentication
* in secure connections pairing
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual ble_error_t secure_connections_oob_received(
const address_t &address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) = 0;
/**
* Supply the stack with the OOB data for secure connections.
*
* @param[in] address address of the peer device oob data is needed for
* @return True if oob data present, false if not or if the functionality
* is not implemented.
*/
virtual bool is_secure_connections_oob_present(
const address_t &address
) = 0;
/* Entry points for the underlying stack to report events back to the user. */
public:
/**

View File

@ -519,6 +519,14 @@ ble_error_t GenericSecurityManager::setOOBDataUsage(
cb->attempt_oob = useOOB;
cb->oob_mitm_protection = OOBProvidesMITM;
_oob_temporary_key_creator_address = cb->local_address;
get_random_data(_oob_temporary_key.buffer(), 16);
eventHandler->legacyPairingOobGenerated(
&_oob_temporary_key_creator_address,
&_oob_temporary_key
);
_pal.generate_secure_connections_oob(connection);
return BLE_ERROR_NONE;
@ -558,7 +566,20 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived(
return BLE_ERROR_INVALID_PARAM;
}
return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk);
_oob_temporary_key = *tk;
_oob_temporary_key_creator_address = *address;
if (cb->peer_address == _oob_temporary_key_creator_address) {
cb->attempt_oob = true;
}
if (cb->legacy_pairing_oob_request_pending) {
on_legacy_pairing_oob_request(cb->connection);
/* legacy_pairing_oob_request_pending stops us from
* going into a loop of asking the user for oob
* so this reset needs to happen after the call above */
cb->legacy_pairing_oob_request_pending = false;
}
}
return BLE_ERROR_NONE;
}
@ -569,7 +590,10 @@ ble_error_t GenericSecurityManager::oobReceived(
const oob_confirm_t *confirm
) {
if (address && random && confirm) {
return _pal.secure_connections_oob_received(*address, *random, *confirm);
_oob_peer_address = *address;
_oob_peer_random = *random;
_oob_peer_confirm = *confirm;
return BLE_ERROR_NONE;
}
return BLE_ERROR_INVALID_PARAM;
@ -702,7 +726,7 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection)
cb->oob_present = cb->attempt_oob;
if (_default_authentication.get_secure_connections()) {
cb->oob_present = _pal.is_secure_connections_oob_present(cb->peer_address);
cb->oob_present = (cb->peer_address == _oob_peer_address);
}
}
@ -710,6 +734,11 @@ void GenericSecurityManager::set_mitm_performed(connection_handle_t connection,
ControlBlock_t *cb = get_control_block(connection);
if (cb) {
cb->mitm_performed = enable;
/* whenever we reset mitm performed we also reset pending requests
* as this happens whenever a new pairing attempt happens */
if (!enable) {
cb->legacy_pairing_oob_request_pending = false;
}
}
}
@ -856,16 +885,23 @@ void GenericSecurityManager::on_slave_security_request(
return;
}
if (authentication.get_secure_connections()
&& _default_authentication.get_secure_connections()
&& !cb->secure_connections_paired) {
requestPairing(connection);
bool pairing_required = false;
if (authentication.get_secure_connections() && !cb->secure_connections_paired
&& _default_authentication.get_secure_connections()) {
pairing_required = true;
}
if (authentication.get_mitm()
&& !cb->ltk_mitm_protected) {
if (authentication.get_mitm() && !cb->ltk_mitm_protected) {
pairing_required = true;
cb->mitm_requested = true;
}
if (pairing_required) {
requestPairing(connection);
} else if (!cb->encryption_requested) {
/* this will refresh keys if encryption is already present */
enable_encryption(connection);
}
}
@ -950,17 +986,52 @@ void GenericSecurityManager::on_confirmation_request(connection_handle_t connect
eventHandler->confirmationRequest(connection);
}
void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
void GenericSecurityManager::on_secure_connections_oob_request(connection_handle_t connection) {
set_mitm_performed(connection);
eventHandler->legacyPairingOobRequest(connection);
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
return;
}
if (cb->peer_address == _oob_peer_address) {
_pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm);
} else {
_pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE);
}
}
void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t connection) {
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
return;
}
if (cb->peer_address == _oob_temporary_key_creator_address
|| cb->local_address == _oob_temporary_key_creator_address) {
set_mitm_performed(connection);
_pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key);
} else if (!cb->legacy_pairing_oob_request_pending) {
cb->legacy_pairing_oob_request_pending = true;
eventHandler->legacyPairingOobRequest(connection);
}
}
void GenericSecurityManager::on_secure_connections_oob_generated(
const address_t &local_address,
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) {
eventHandler->oobGenerated(&local_address, &random, &confirm);
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
return;
}
eventHandler->oobGenerated(&cb->local_address, &random, &confirm);
_oob_local_random = random;
}
////////////////////////////////////////////////////////////////////////////
@ -1118,7 +1189,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
mitm_performed(false),
attempt_oob(false),
oob_mitm_protection(false),
oob_present(false) { }
oob_present(false),
legacy_pairing_oob_request_pending(false) { }
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
{

View File

@ -85,16 +85,42 @@ public:
virtual ble_error_t clear_resolving_list();
////////////////////////////////////////////////////////////////////////////
// Feature support
// Pairing
//
/**
* @see ::ble::pal::SecurityManager::set_secure_connections_support
* @see ::ble::pal::SecurityManager::send_pairing_request
*/
virtual ble_error_t set_secure_connections_support(
bool enabled, bool secure_connections_only = false
virtual ble_error_t send_pairing_request(
connection_handle_t connection,
bool oob_data_flag,
AuthenticationMask authentication_requirements,
KeyDistribution initiator_dist,
KeyDistribution responder_dist
);
/**
* @see ::ble::pal::SecurityManager::send_pairing_response
*/
virtual ble_error_t send_pairing_response(
connection_handle_t connection,
bool oob_data_flag,
AuthenticationMask authentication_requirements,
KeyDistribution initiator_dist,
KeyDistribution responder_dist
);
/**
* @see ::ble::pal::SecurityManager::cancel_pairing
*/
virtual ble_error_t cancel_pairing(
connection_handle_t connection, pairing_failure_t reason
);
////////////////////////////////////////////////////////////////////////////
// Feature support
//
/**
* @see ::ble::pal::SecurityManager::get_secure_connections_support
*/
@ -102,6 +128,11 @@ public:
bool &enabled
);
/**
* @see ::ble::pal::SecurityManager::set_io_capability
*/
virtual ble_error_t set_io_capability(io_capability_t io_capability);
////////////////////////////////////////////////////////////////////////////
// Security settings
//
@ -120,6 +151,17 @@ public:
connection_handle_t, uint16_t &timeout_in_10ms
);
/**
* @see ::ble::pal::SecurityManager::set_encryption_key_requirements
*/
virtual ble_error_t set_encryption_key_requirements(
uint8_t min_encryption_key_size,
uint8_t max_encryption_key_size
);
/**
* @see ::ble::pal::SecurityManager::slave_security_request
*/
virtual ble_error_t slave_security_request(
connection_handle_t connection,
AuthenticationMask authentication
@ -197,61 +239,10 @@ public:
*/
virtual ble_error_t set_csrk(const csrk_t &csrk);
////////////////////////////////////////////////////////////////////////////
// Global parameters
//
/**
* @see ::ble::pal::SecurityManager::set_display_passkey
*/
virtual ble_error_t set_display_passkey(passkey_num_t passkey);
/**
* @see ::ble::pal::SecurityManager::set_io_capability
*/
virtual ble_error_t set_io_capability(io_capability_t io_capability);
/**
* @see ::ble::pal::SecurityManager::set_encryption_key_requirements
*/
virtual ble_error_t set_encryption_key_requirements(
uint8_t min_encryption_key_size,
uint8_t max_encryption_key_size
);
////////////////////////////////////////////////////////////////////////////
// Authentication
//
/**
* @see ::ble::pal::SecurityManager::send_pairing_request
*/
virtual ble_error_t send_pairing_request(
connection_handle_t connection,
bool oob_data_flag,
AuthenticationMask authentication_requirements,
KeyDistribution initiator_dist,
KeyDistribution responder_dist
);
/**
* @see ::ble::pal::SecurityManager::send_pairing_response
*/
virtual ble_error_t send_pairing_response(
connection_handle_t connection,
bool oob_data_flag,
AuthenticationMask authentication_requirements,
KeyDistribution initiator_dist,
KeyDistribution responder_dist
);
/**
* @see ::ble::pal::SecurityManager::cancel_pairing
*/
virtual ble_error_t cancel_pairing(
connection_handle_t connection, pairing_failure_t reason
);
/**
* @see ::ble::pal::SecurityManager::get_random_data
*/
@ -261,6 +252,11 @@ public:
// MITM
//
/**
* @see ::ble::pal::SecurityManager::set_display_passkey
*/
virtual ble_error_t set_display_passkey(passkey_num_t passkey);
/**
* @see ::ble::pal::SecurityManager::passkey_request_reply
*/
@ -269,6 +265,16 @@ public:
passkey_num_t passkey
);
/**
* @see ::ble::pal::SecurityManager::secure_connections_oob_request_reply
*/
virtual ble_error_t secure_connections_oob_request_reply(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random,
const oob_confirm_t &peer_confirm
);
/**
* @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply
*/
@ -298,22 +304,6 @@ public:
connection_handle_t connection
);
/**
* @see ::ble::pal::SecurityManager::secure_connections_oob_received
*/
virtual ble_error_t secure_connections_oob_received(
const address_t &address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
);
/**
* @see ::ble::pal::SecurityManager::is_secure_connections_oob_present
*/
virtual bool is_secure_connections_oob_present(
const address_t &address
);
// singleton of the ARM Cordio Security Manager
static CordioSecurityManager &get_security_manager();
@ -325,13 +315,6 @@ private:
passkey_num_t _default_passkey;
bool _lesc_keys_generated;
uint8_t _public_key_x[SEC_ECC_KEY_LEN];
bool _peer_oob_present;
address_t _peer_oob_address;
oob_lesc_value_t _peer_oob_random;
oob_confirm_t _peer_oob_confirm;
bool _own_oob_present;
uint8_t _confirm[SMP_CONFIRM_LEN];
uint8_t _random[SMP_RAND_LEN];
};
} // cordio

View File

@ -30,15 +30,8 @@ CordioSecurityManager::CordioSecurityManager() :
::ble::pal::SecurityManager(),
_use_default_passkey(false),
_default_passkey(0),
_lesc_keys_generated(false),
_public_key_x(),
_peer_oob_present(false),
_peer_oob_address(),
_peer_oob_random(),
_peer_oob_confirm(),
_own_oob_present(false),
_confirm(),
_random()
_lesc_keys_generated(false),
_public_key_x()
{
}
@ -54,15 +47,16 @@ CordioSecurityManager::~CordioSecurityManager()
ble_error_t CordioSecurityManager::initialize()
{
// reset local state
// reset local state
_use_default_passkey = false;
_default_passkey = 0;
_lesc_keys_generated = false;
_peer_oob_present = false;
_own_oob_present = false;
_lesc_keys_generated = false;
// generate a new set of keys
DmSecGenerateEccKeyReq();
#if 0
// FIXME: need help from the stack or local calculation
// generate a new set of keys
DmSecGenerateEccKeyReq();
#endif
return BLE_ERROR_NONE;
}
@ -74,7 +68,7 @@ ble_error_t CordioSecurityManager::terminate()
ble_error_t CordioSecurityManager::reset()
{
initialize();
initialize();
return BLE_ERROR_NONE;
}
@ -115,6 +109,8 @@ ble_error_t CordioSecurityManager::clear_resolving_list()
// Feature support
//
// FIXME: Enable when new function available in the pal.
#if 0
ble_error_t CordioSecurityManager::set_secure_connections_support(
bool enabled, bool secure_connections_only
) {
@ -126,6 +122,7 @@ ble_error_t CordioSecurityManager::set_secure_connections_support(
}
return BLE_ERROR_NONE;
}
#endif
ble_error_t CordioSecurityManager::get_secure_connections_support(
bool &enabled
@ -413,8 +410,8 @@ ble_error_t CordioSecurityManager::send_keypress_notification(
ble_error_t CordioSecurityManager::generate_secure_connections_oob(
connection_handle_t connection
) {
// Note: this is not tie to a connection; only one oob value is present in
// the pal.
// Note: this is not tie to a connection; only one oob value is present in
// the pal.
uint8_t oobLocalRandom[SMP_RAND_LEN];
SecRand(oobLocalRandom, SMP_RAND_LEN);
@ -423,28 +420,26 @@ ble_error_t CordioSecurityManager::generate_secure_connections_oob(
return BLE_ERROR_NOT_IMPLEMENTED;
}
ble_error_t CordioSecurityManager::secure_connections_oob_received(
const address_t &address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
ble_error_t CordioSecurityManager::secure_connections_oob_request_reply(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random,
const oob_confirm_t &peer_confirm
) {
_peer_oob_present = true;
_peer_oob_address = address;
_peer_oob_random = random;
_peer_oob_confirm = confirm;
dmSecLescOobCfg_t oob_config = { 0 };
memcpy(oob_config.localRandom, local_random.data(), local_random.size());
// FIXME:
// memcpy(oob_config.localConfirm, ?, ?);
memcpy(oob_config.peerRandom, peer_random.data(), peer_random.size());
memcpy(oob_config.peerConfirm, peer_confirm.data(), peer_confirm.size());
DmSecSetOob(connection, &oob_config);
DmSecAuthRsp(connection, 0, NULL);
return BLE_ERROR_NONE;
}
bool CordioSecurityManager::is_secure_connections_oob_present(
const address_t &address
) {
if (!_peer_oob_present) {
return false;
}
return address == _peer_oob_address;
}
CordioSecurityManager& CordioSecurityManager::get_security_manager()
{
static CordioSecurityManager _security_manager;
@ -515,11 +510,11 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) {
connection_handle_t connection = evt->hdr.param;
if (evt->oob) {
// FIXME: Nothing in the API indicates if smp or sc OOB are
// requested.
// To set secure connection OOB:
// - DmSecSetOob(connection, oob_data)
// - DmSecAuthRsp(connection, 0, NULL)
// FIXME: Nothing in the API indicates if smp or sc OOB are
// requested.
// To set secure connection OOB:
// - DmSecSetOob(connection, oob_data)
// - DmSecAuthRsp(connection, 0, NULL)
handler->on_legacy_pairing_oob_request(connection);
} else if (evt->display) {
if (get_security_manager()._use_default_passkey) {
@ -644,39 +639,35 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) {
}
case DM_SEC_CALC_OOB_IND: {
dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg;
self._own_oob_present = true;
memcpy(self._confirm, evt->confirm, sizeof(_confirm));
memcpy(self._random, evt->random, sizeof(_random));
handler->on_secure_connections_oob_generated(
address_t(), /* which address should be used ??? */
evt->random,
evt->confirm
);
dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg;
handler->on_secure_connections_oob_generated(
evt->hdr.param,
evt->random,
evt->confirm
);
return true;
}
case DM_SEC_ECC_KEY_IND: {
secEccMsg_t* evt = (secEccMsg_t*) msg;
DmSecSetEccKey(&evt->data.key);
memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(_public_key_x));
self._lesc_keys_generated = true;
secEccMsg_t* evt = (secEccMsg_t*) msg;
DmSecSetEccKey(&evt->data.key);
memcpy(self._public_key_x, evt->data.key.pubKey_x, sizeof(_public_key_x));
self._lesc_keys_generated = true;
return true;
}
case DM_SEC_COMPARE_IND: {
dmSecCnfIndEvt_t* evt = (dmSecCnfIndEvt_t*) msg;
handler->on_passkey_display(
/* connection */ evt->hdr.param,
DmSecGetCompareValue(evt->confirm)
);
handler->on_confirmation_request(/* connection */ evt->hdr.param);
return true;
dmSecCnfIndEvt_t* evt = (dmSecCnfIndEvt_t*) msg;
handler->on_passkey_display(
/* connection */ evt->hdr.param,
DmSecGetCompareValue(evt->confirm)
);
handler->on_confirmation_request(/* connection */ evt->hdr.param);
return true;
}
case DM_SEC_KEYPRESS_IND: {
dmSecKeypressIndEvt_t* evt = (dmSecKeypressIndEvt_t*) msg;
handler->on_keypress_notification(
/* connection */ evt->hdr.param,
(Keypress_t) evt->notificationType