Merge pull request #25 from paul-szczepanek-arm/oob-gen

generate oob at will and without passing in connection handle
pull/6932/head
Paul Szczepanek 2018-04-03 15:30:21 +01:00 committed by GitHub
commit 381b99bc61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 162 additions and 73 deletions

View File

@ -261,6 +261,27 @@ private:
uint8_t ascii[PASSKEY_LEN];
};
/**
* Returns true if every byte is equal to zero
*/
template <class byte_array_class>
bool is_all_zeros(byte_array_class &byte_array) {
for (size_t i = 0; i < byte_array.size(); i++) {
if (byte_array[i] != 0) {
return false;
}
}
return true;
}
/**
* Zero out all bytes
*/
template <class byte_array_class>
void set_all_zeros(byte_array_class &byte_array) {
memset(&byte_array[0], 0x00, byte_array.size());
}
template <size_t array_size>
struct byte_array_t {
/**

View File

@ -735,15 +735,48 @@ public:
// MITM
//
/**
* Generate OOB data with the given address. If Secure Connections is supported this will
* also generate Secure Connections OOB data on top of legacy pairing OOB data. This can be used
* to generate such data before the connection takes place.
*
* In this model the OOB exchange takes place before the devices connect. Devices should establish
* communication over another channel and exchange the OOB data. The address provided will be used
* by the peer to associate the received data with the address of the device it will then connect
* to over BLE.
*
* @param[in] address The local address you will use in the connection using this OOB data. This
* address will be returned along with the rest of the OOB data when generation
* is complete. Using an invalid address is illegal.
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual ble_error_t generateOOB(const ble::address_t *address) {
/* Avoid compiler warnings about unused variables */
(void) address;
return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */
}
/**
* Enable OOB data usage during paring. If Secure Connections is supported enabling useOOB will
* generate Secure Connections OOB data through oobGenerated().
* generate Secure Connections OOB data through oobGenerated() on top of legacy pairing OOB data.
*
* You do not have to call this function to return received OOB data. Use legacyPairingOobReceived
* or oobReceived to hand it in. This will allow the stack to use it if possible. You only need to
* call this function to attempt legacy OOB data exchange after pairing start and to inform
* the stack OOB data does not provide MITM protection (by default it is set to provide this).
*
* In this model the OOB exchange takes places after the devices have connected but possibly
* prior to pairing. For secure connections pairing must not be started until after the OOB
* data has been sent and/or received. The address in the OOB data generated will match
* the original address used to establish the connection and will be used by the peer to
* identify which connection the OOB data belongs to.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[in] useOOB If set to true, authenticate using OOB data.
* @param[in] OOBProvidesMITM If set to true keys exchanged during pairing using OOB data
* will provide MITM protection. This indicates that the form
* of exchange used by the OOB data itself provides MITM protection.
* will provide Man-in-the-Middle protection. This indicates that
* the form of exchange used by the OOB data itself provides MITM
* protection.
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true) {

View File

@ -192,6 +192,10 @@ public:
// MITM
//
virtual ble_error_t generateOOB(
const address_t *address
);
virtual ble_error_t setOOBDataUsage(
connection_handle_t connection,
bool useOOB,
@ -240,6 +244,11 @@ public:
_legacy_pairing_allowed(true),
_master_sends_keys(false) {
_pal.set_event_handler(this);
/* We create a fake value for oob to allow creation of the next oob which needs
* the last process to finish first before restarting (this is to simplify checking).
* This fake value will not be used as the oob address is currently invalid */
_oob_local_random[0] = 1;
}
////////////////////////////////////////////////////////////////////////////
@ -441,6 +450,7 @@ private:
pal::ConnectionEventMonitor &_connection_monitor;
/* OOB data */
address_t _oob_local_address;
address_t _oob_peer_address;
oob_lesc_value_t _oob_peer_random;
oob_confirm_t _oob_peer_confirm;
@ -572,7 +582,6 @@ public:
/** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated
*/
virtual void on_secure_connections_oob_generated(
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
);

View File

@ -399,7 +399,6 @@ public:
* @return BLE_ERROR_NONE or appropriate error code indicating the failure reason.
*/
virtual void on_secure_connections_oob_generated(
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) = 0;
@ -545,21 +544,21 @@ public:
/**
* Initialise stack. Called before first use.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t initialize() = 0;
/**
* Finalise all actions. Called before shutdown.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t terminate() = 0;
/**
* Reset to same state as after initialize.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t reset() = 0;
@ -574,7 +573,7 @@ public:
* @warning: The number of entries is considered fixed.
*
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.41
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual uint8_t read_resolving_list_capacity() = 0;
@ -585,7 +584,7 @@ public:
* @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
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @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,
@ -599,7 +598,7 @@ public:
* @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
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @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,
@ -610,7 +609,7 @@ public:
* Remove all devices from the resolving list.
*
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E: 7.8.40
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t clear_resolving_list() = 0;
@ -627,7 +626,7 @@ public:
* @param[in] initiator_dist key distribution
* @param[in] responder_dist key distribution
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.1
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t send_pairing_request(
connection_handle_t connection,
@ -646,7 +645,7 @@ public:
* @param[in] authentication_requirements authentication requirements
* @param[in] initiator_dist key distribution
* @param[in] responder_dist key distribution
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t send_pairing_response(
connection_handle_t connection,
@ -662,7 +661,7 @@ public:
* @param[in] connection connection handle
* @param[in] reason pairing failure error
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 3.5.5
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t cancel_pairing(
connection_handle_t connection,
@ -677,7 +676,7 @@ public:
* Check if the Secure Connections feature is supported by the stack and controller.
*
* @param[out] enabled true if SC are supported
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t get_secure_connections_support(
bool &enabled
@ -687,7 +686,7 @@ public:
* Set the IO capability that will be used during pairing feature exchange.
*
* @param[in] io_capability type of IO capabilities available on the local device
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_io_capability(
io_capability_t io_capability
@ -703,7 +702,7 @@ public:
*
* @param[in] connection connection handle
* @param[in] timeout_in_10ms time measured in units of 10 milliseconds
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_authentication_timeout(
connection_handle_t connection,
@ -716,7 +715,7 @@ public:
*
* @param[in] connection connection handle
* @param[out] timeout_in_10ms time measured in units of 10 milliseconds
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t get_authentication_timeout(
connection_handle_t connection,
@ -734,7 +733,7 @@ public:
* required for pairing. This value shall be in the range
* [min_encryption_key_size : 16].
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_encryption_key_requirements(
uint8_t min_encryption_key_size,
@ -749,7 +748,7 @@ public:
*
* @param[in] connection connection handle
* @param[in] authentication authentication requirements
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t slave_security_request(
connection_handle_t connection,
@ -770,7 +769,7 @@ public:
* @param[in] ediv encryption diversifier from the peer
* @param[in] rand random value from the peer
* @param[in] mitm does the LTK have man in the middle protection
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t enable_encryption(
connection_handle_t connection,
@ -787,7 +786,7 @@ public:
* @param[in] connection connection handle
* @param[in] ltk long term key from the peer
* @param[in] mitm does the LTK have man in the middle protection
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t enable_encryption(
connection_handle_t connection,
@ -801,7 +800,7 @@ public:
*
* @param[in] key encryption key
* @param[in,out] data data to be encrypted, if successful contains the result
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t encrypt_data(
const byte_array_t<16> &key,
@ -827,7 +826,7 @@ public:
* @param[in] ltk long term key
* @param[in] mitm does the LTK have man in the middle protection
* @param[in] secure_connections is this a secure_connections pairing
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_ltk(
connection_handle_t connection,
@ -840,7 +839,7 @@ public:
* Inform the stack we don't have the LTK.
*
* @param[in] connection connection handle
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_ltk_not_found(
connection_handle_t connection
@ -850,7 +849,7 @@ public:
* Set the local IRK.
*
* @param[in] irk identity resolution key
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_irk(
const irk_t &irk
@ -860,7 +859,7 @@ public:
* Set the local CSRK.
*
* @param[in] csrk signing key
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_csrk(
const csrk_t &csrk
@ -875,7 +874,7 @@ public:
*
* @param[out] random_data returns 8 octets of random data
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part H 2
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t get_random_data(
byte_array_t<8> &random_data
@ -903,7 +902,7 @@ public:
* passkey is set to 0 then the security manager generates a random
* passkey every time it calls SecurityManagerEvent::on_passkey_display.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t set_display_passkey(
passkey_num_t passkey
@ -912,7 +911,7 @@ public:
/**
* Reply to a passkey request received from the SecurityManagerEventHandler.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t passkey_request_reply(
connection_handle_t connection,
@ -927,7 +926,7 @@ public:
* @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
* @return 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,
@ -941,7 +940,7 @@ public:
*
* @param[in] connection connection handle
* @param[in] oob_data pointer to out of band data
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t legacy_pairing_oob_request_reply(
connection_handle_t connection,
@ -954,7 +953,7 @@ public:
*
* @param[in] connection connection handle
* @param[in] confirmation true if the user indicated the numbers match
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t confirmation_entered(
connection_handle_t connection,
@ -967,7 +966,7 @@ public:
*
* @param[in] connection connection handle
* @param[in] keypress type of keypress event
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t send_keypress_notification(
connection_handle_t connection,
@ -976,12 +975,9 @@ public:
/**
* Generate local OOB data to be sent to the application which sends it to the peer.
*
* @param[in] connectionHandle Handle to identify the connection.
* @return BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t generate_secure_connections_oob(
connection_handle_t connection
) = 0;
virtual ble_error_t generate_secure_connections_oob() = 0;
/* Entry points for the underlying stack to report events back to the user. */
public:

View File

@ -506,6 +506,43 @@ ble_error_t GenericSecurityManager::requestAuthentication(connection_handle_t co
// MITM
//
ble_error_t GenericSecurityManager::generateOOB(
const address_t *address
) {
/* legacy pairing */
ble_error_t status = get_random_data(_oob_temporary_key.buffer(), 16);
if (status == BLE_ERROR_NONE) {
_oob_temporary_key_creator_address = *address;
eventHandler->legacyPairingOobGenerated(
&_oob_temporary_key_creator_address,
&_oob_temporary_key
);
} else {
return status;
}
/* Secure connections. Avoid generating if we're already waiting for it.
* If a local random is set to 0 it means we're already calculating. */
if (!is_all_zeros(_oob_local_random)) {
status = _pal.generate_secure_connections_oob();
if (status == BLE_ERROR_NONE) {
_oob_local_address = *address;
/* this will be updated when calculation completes,
* a value of all zeros is an invalid random value */
set_all_zeros(_oob_local_random);
} else if (status != BLE_ERROR_NOT_IMPLEMENTED) {
return status;
}
} else {
return BLE_STACK_BUSY;
}
return BLE_ERROR_NONE;
}
ble_error_t GenericSecurityManager::setOOBDataUsage(
connection_handle_t connection,
bool useOOB,
@ -519,17 +556,11 @@ 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;
if (useOOB) {
return generateOOB(&cb->local_address);
} else {
return BLE_ERROR_NONE;
}
}
ble_error_t GenericSecurityManager::confirmationEntered(
@ -720,13 +751,18 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection)
return;
}
/* only update the oob state if we support secure connections,
* otherwise follow the user set preference for providing legacy
* pairing oob data */
cb->oob_present = cb->attempt_oob;
/* if we support secure connection we only care about secure connections oob data */
if (_default_authentication.get_secure_connections()) {
cb->oob_present = (cb->peer_address == _oob_peer_address);
} else {
/* otherwise for legacy pairing we first set the oob based on set preference */
cb->oob_present = cb->attempt_oob;
/* and also turn it on if we have oob data for legacy pairing */
if (cb->peer_address == _oob_temporary_key_creator_address
|| cb->local_address == _oob_temporary_key_creator_address) {
cb->oob_present = true;
}
}
}
@ -996,6 +1032,8 @@ void GenericSecurityManager::on_secure_connections_oob_request(connection_handle
if (cb->peer_address == _oob_peer_address) {
_pal.secure_connections_oob_request_reply(connection, _oob_local_random, _oob_peer_random, _oob_peer_confirm);
/* do not re-use peer OOB */
set_all_zeros(_oob_peer_address);
} else {
_pal.cancel_pairing(connection, pairing_failure_t::OOB_NOT_AVAILABLE);
}
@ -1013,6 +1051,11 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c
set_mitm_performed(connection);
_pal.legacy_pairing_oob_request_reply(connection, _oob_temporary_key);
/* do not re-use peer OOB */
if (cb->peer_address == _oob_temporary_key_creator_address) {
set_all_zeros(_oob_temporary_key_creator_address);
}
} else if (!cb->legacy_pairing_oob_request_pending) {
cb->legacy_pairing_oob_request_pending = true;
@ -1022,15 +1065,10 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c
}
void GenericSecurityManager::on_secure_connections_oob_generated(
connection_handle_t connection,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) {
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
return;
}
eventHandler->oobGenerated(&cb->local_address, &random, &confirm);
eventHandler->oobGenerated(&_oob_local_address, &random, &confirm);
_oob_local_random = random;
}

View File

@ -300,9 +300,7 @@ public:
/**
* @see ::ble::pal::SecurityManager::generate_secure_connections_oob
*/
virtual ble_error_t generate_secure_connections_oob(
connection_handle_t connection
);
virtual ble_error_t generate_secure_connections_oob();
// singleton of the ARM Cordio Security Manager
static CordioSecurityManager &get_security_manager();

View File

@ -407,17 +407,12 @@ ble_error_t CordioSecurityManager::send_keypress_notification(
return BLE_ERROR_NONE;
}
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.
ble_error_t CordioSecurityManager::generate_secure_connections_oob() {
uint8_t oobLocalRandom[SMP_RAND_LEN];
SecRand(oobLocalRandom, SMP_RAND_LEN);
DmSecCalcOobReq(oobLocalRandom, _public_key_x);
return BLE_ERROR_NOT_IMPLEMENTED;
return BLE_ERROR_NONE;
}
ble_error_t CordioSecurityManager::secure_connections_oob_request_reply(
@ -641,7 +636,6 @@ bool CordioSecurityManager::sm_handler(const wsfMsgHdr_t* msg) {
case DM_SEC_CALC_OOB_IND: {
dmSecOobCalcIndEvt_t* evt = (dmSecOobCalcIndEvt_t*) msg;
handler->on_secure_connections_oob_generated(
evt->hdr.param,
evt->random,
evt->confirm
);