handling OOB data generation and verification now pushed down to PAL level

pull/6932/head
paul-szczepanek-arm 2018-03-02 15:48:29 +00:00
parent a6e27b1b86
commit b8ba99a184
7 changed files with 95 additions and 269 deletions

View File

@ -238,8 +238,7 @@ public:
_default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL),
_pairing_authorisation_required(false),
_legacy_pairing_allowed(true),
_master_sends_keys(false),
_public_keys_generated(false) {
_master_sends_keys(false) {
_pal.set_event_handler(this);
}
@ -321,17 +320,6 @@ private:
const csrk_t *csrk
);
#if defined(MBEDTLS_CMAC_C)
/**
* Generate local OOB data to be sent to the application which sends it to the peer.
*
* @param[in] connectionHandle Handle to identify the connection.
*/
void generate_secure_connections_oob(
connection_handle_t connection
);
#endif
/**
* Updates the entry for the connection with OOB data presence.
*
@ -341,26 +329,6 @@ private:
connection_handle_t connection
);
#if defined(MBEDTLS_CMAC_C)
/**
* Calculate the confirmation value for secure connections OOB data based
* on local public key and a random number.
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.2.6
* @param[in] U public key x component
* @param[in] V public key y component
* @param[in] X random number
* @param[out] confirm confirmation value
* @return true if cryptography functioned worked
*/
static bool crypto_toolbox_f4(
const public_key_t &U,
const public_key_t &V,
const oob_lesc_value_t &X,
oob_confirm_t &confirm
);
#endif
/**
* Set the MITM protection setting on the database entry
*
@ -477,13 +445,6 @@ private:
bool _pairing_authorisation_required;
bool _legacy_pairing_allowed;
bool _master_sends_keys;
bool _public_keys_generated;
/** There is always only one OOB data set stored at a time */
address_t _peer_sc_oob_address;
oob_lesc_value_t _peer_sc_oob_random;
oob_confirm_t _peer_sc_oob_confirm;
oob_lesc_value_t _local_sc_oob_random;
static const size_t MAX_CONTROL_BLOCKS = 5;
ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS];
@ -593,25 +554,18 @@ public:
connection_handle_t connection
);
/** @copydoc ble::pal::SecurityManager::on_oob_data_verification_request
/** @copydoc ble::pal::SecurityManager::on_secure_connections_oob_generated
*/
virtual void on_oob_data_verification_request(
connection_handle_t connection,
const public_key_coord_t &peer_public_key_x,
const public_key_coord_t &peer_public_key_y
virtual void on_secure_connections_oob_generated(
const address_t &local_address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
);
////////////////////////////////////////////////////////////////////////////
// Keys
//
/** @copydoc ble::pal::SecurityManager::on_public_key_generated
*/
virtual void on_public_key_generated(
const public_key_coord_t &public_key_x,
const public_key_coord_t &public_key_y
);
/** @copydoc ble::pal::SecurityManager::on_secure_connections_ltk_generated
*/
virtual void on_secure_connections_ltk_generated(

View File

@ -240,24 +240,6 @@ public:
_local_csrk = csrk;
}
/* public key */
virtual const public_key_coord_t& get_public_key_x() {
return _public_key_x;
}
virtual const public_key_coord_t& get_public_key_y() {
return _public_key_y;
}
virtual void set_public_key(
const public_key_coord_t &public_key_x,
const public_key_coord_t &public_key_y
) {
_public_key_x = public_key_x;
_public_key_y = public_key_y;
}
/* list management */
virtual entry_handle_t open_entry(
@ -362,8 +344,6 @@ private:
entry_t _entries[MAX_ENTRIES];
SecurityEntryIdentity_t _local_identity;
csrk_t _local_csrk;
public_key_coord_t _public_key_x;
public_key_coord_t _public_key_y;
};
} /* namespace pal */

View File

@ -371,7 +371,7 @@ public:
* Request OOB data from the user application.
*
* @param[in] connection connection handle
* @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_data_request_reply
* @note shall be followed by: pal::SecurityManager::legacy_pairing_oob_request_reply
* or a cancellation of the procedure.
*/
virtual void on_legacy_pairing_oob_request(
@ -379,32 +379,24 @@ public:
) = 0;
/**
* Request OOB data to be verified against received public keys.
* Send OOB data to the application for transport to the peer.
*
* @param[in] public_key_x newly generated public key (x coordinate)
* @param[in] public_key_y newly generated public key (y coordinate)
* @param[in] address address of the local device
* @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_oob_data_verification_request(
connection_handle_t connection,
const public_key_coord_t &peer_public_key_x,
const public_key_coord_t &peer_public_key_y
virtual void on_secure_connections_oob_generated(
const address_t &local_address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) = 0;
////////////////////////////////////////////////////////////////////////////
// Keys
//
/**
* Provide the local public key.
*
* @param[in] public_key_x newly generated public key (x coordinate)
* @param[in] public_key_y newly generated public key (y coordinate)
*/
virtual void on_public_key_generated(
const public_key_coord_t &public_key_x,
const public_key_coord_t &public_key_y
) = 0;
/**
* Store the results of key generation of the stage 2 of secure connections pairing
* @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.6.5
@ -863,14 +855,6 @@ public:
const csrk_t &csrk
) = 0;
/**
* Generate the Public key. This will also generate the private key.
* Public key will be returned as an event handler callback when it's ready.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t generate_public_key() = 0;
////////////////////////////////////////////////////////////////////////////
// Authentication
//
@ -931,7 +915,7 @@ public:
* @param[in] oob_data pointer to out of band data
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
*/
virtual ble_error_t legacy_pairing_oob_data_request_reply(
virtual ble_error_t legacy_pairing_oob_request_reply(
connection_handle_t connection,
const oob_tk_t &oob_data
) = 0;
@ -963,20 +947,38 @@ public:
) = 0;
/**
* Notify the stack that the OOB data has been verified and supply the peer's random number.
* If the verification failed this will not be called and cancel_pairing will be called instead.
* Generate local OOB data to be sent to the application which sends it to the peer.
*
* @param[in] connection connection handle
* @param[in] local_random random number sent from the local device to be used in further
* calculations by the stack, set to 0 if peer reported no OOB present
* @param[in] peer_random random number from the peer to be used in further
* calculations by the stack, set to 0 if no OOB data received
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
* @param[in] connectionHandle Handle to identify the connection.
*/
virtual ble_error_t oob_data_verified(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random
virtual ble_error_t generate_secure_connections_oob(
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_connectinos_oob_present(
const address_t &address
) = 0;
/* Entry points for the underlying stack to report events back to the user. */

View File

@ -286,33 +286,6 @@ public:
*/
virtual void set_local_csrk(const csrk_t &csrk) = 0;
/* public keys */
/**
* Return local public key.
*
* @return ref to x component of public key
*/
virtual const public_key_coord_t& get_public_key_x() = 0;
/**
* Return local public key.
*
* @return ref to y component of public key
*/
virtual const public_key_coord_t& get_public_key_y() = 0;
/**
* Set local public key.
*
* @param[in] public_key_x new public key value of the x coordinate
* @param[in] public_key_y new public key value of the y coordinate
*/
virtual void set_public_key(
const public_key_coord_t &public_key_x,
const public_key_coord_t &public_key_y
) = 0;
/* list management */
/**

View File

@ -17,9 +17,6 @@
#include "ble/SecurityManager.h"
#include "ble/pal/PalSecurityManager.h"
#include "ble/generic/GenericSecurityManager.h"
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
using ble::pal::advertising_peer_address_type_t;
using ble::pal::AuthenticationMask;
@ -71,14 +68,11 @@ ble_error_t GenericSecurityManager::init(
_connection_monitor.set_connection_event_handler(this);
_pal.set_event_handler(this);
_pal.generate_public_key();
return BLE_ERROR_NONE;
}
ble_error_t GenericSecurityManager::reset(void) {
_db.sync();
_public_keys_generated = false;
SecurityManager::reset();
return BLE_ERROR_NONE;
@ -519,11 +513,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage(
cb->attempt_oob = useOOB;
cb->oob_mitm_protection = OOBProvidesMITM;
#if defined(MBEDTLS_CMAC_C)
if (_public_keys_generated) {
generate_secure_connections_oob(connection);
}
#endif
_pal.generate_secure_connections_oob(connection);
return BLE_ERROR_NONE;
}
@ -562,7 +552,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived(
return BLE_ERROR_INVALID_PARAM;
}
return _pal.legacy_pairing_oob_data_request_reply(cb->connection, *tk);
return _pal.legacy_pairing_oob_request_reply(cb->connection, *tk);
}
return BLE_ERROR_NONE;
}
@ -573,10 +563,7 @@ ble_error_t GenericSecurityManager::oobReceived(
const oob_confirm_t *confirm
) {
if (address && random && confirm) {
_peer_sc_oob_address = *address;
_peer_sc_oob_random = *random;
_peer_sc_oob_confirm = *confirm;
return BLE_ERROR_NONE;
return _pal.secure_connections_oob_received(*address, *random, *confirm);
}
return BLE_ERROR_INVALID_PARAM;
@ -697,40 +684,6 @@ void GenericSecurityManager::return_csrk_cb(
);
}
#if defined(MBEDTLS_CMAC_C)
void GenericSecurityManager::generate_secure_connections_oob(
connection_handle_t connection
) {
oob_confirm_t confirm;
oob_lesc_value_t random;
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
return;
}
ble_error_t ret = get_random_data(random.buffer(), random.size());
if (ret != BLE_ERROR_NONE) {
return;
}
crypto_toolbox_f4(
_db.get_public_key_x(),
_db.get_public_key_y(),
random,
confirm
);
eventHandler->oobGenerated(
&cb->local_address,
&random,
&confirm
);
_local_sc_oob_random = random;
}
#endif
void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
ControlBlock_t *cb = get_control_block(connection);
if (!cb) {
@ -743,45 +696,10 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection)
cb->oob_present = cb->attempt_oob;
if (_default_authentication.get_secure_connections()) {
cb->oob_present = false;
#if defined(MBEDTLS_CMAC_C)
if (cb->peer_address == _peer_sc_oob_address) {
cb->oob_present = true;
}
#endif
cb->oob_present = _pal.is_secure_connectinos_oob_present(cb->peer_address);
}
}
#if defined(MBEDTLS_CMAC_C)
bool GenericSecurityManager::crypto_toolbox_f4(
const public_key_coord_t& U,
const public_key_coord_t& V,
const oob_lesc_value_t& X,
oob_confirm_t& confirm
) {
mbedtls_cipher_context_t context;
const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
const unsigned char Z = 0;
bool success = false;
mbedtls_cipher_init(&context);
/* it's either this chaining or a goto */
if (mbedtls_cipher_setup(&context, info) == 0
&& mbedtls_cipher_cmac_starts(&context, X.data(), 128) == 0
&& mbedtls_cipher_cmac_update(&context, U.data(), 16) == 0
&& mbedtls_cipher_cmac_update(&context, V.data(), 16) == 0
&& mbedtls_cipher_cmac_update(&context, &Z, 1) == 0
&& mbedtls_cipher_cmac_finish(&context, &confirm[0]) == 0) {
success = true;
}
mbedtls_cipher_free(&context);
return success;
}
#endif
void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) {
ControlBlock_t *cb = get_control_block(connection);
if (cb) {
@ -1031,44 +949,18 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c
eventHandler->legacyPairingOobRequest(connection);
}
void GenericSecurityManager::on_oob_data_verification_request(
connection_handle_t connection,
const public_key_coord_t &peer_public_key_x,
const public_key_coord_t &peer_public_key_y
void GenericSecurityManager::on_secure_connections_oob_generated(
const address_t &local_address,
const oob_lesc_value_t &random,
const oob_confirm_t &confirm
) {
#if defined(MBEDTLS_CMAC_C)
ControlBlock_t *cb = get_control_block(connection);
oob_confirm_t confirm_verify;
crypto_toolbox_f4(
peer_public_key_x,
peer_public_key_y,
_peer_sc_oob_random,
confirm_verify
);
if (cb && (cb->peer_address == _peer_sc_oob_address)
&& (confirm_verify == _peer_sc_oob_confirm)) {
_pal.oob_data_verified(connection, _local_sc_oob_random, _peer_sc_oob_random);
} else {
_pal.cancel_pairing(connection, pairing_failure_t::CONFIRM_VALUE_FAILED);
}
#endif
eventHandler->oobGenerated(&local_address, &random, &confirm);
}
////////////////////////////////////////////////////////////////////////////
// Keys
//
void GenericSecurityManager::on_public_key_generated(
const public_key_coord_t &public_key_x,
const public_key_coord_t &public_key_y
) {
_db.set_public_key(public_key_x, public_key_y);
_public_keys_generated = true;
}
void GenericSecurityManager::on_secure_connections_ltk_generated(
connection_handle_t connection,
const ltk_t &ltk

View File

@ -273,9 +273,9 @@ public:
);
/**
* @see ::ble::pal::SecurityManager::legacy_pairing_oob_data_request_reply
* @see ::ble::pal::SecurityManager::legacy_pairing_oob_request_reply
*/
virtual ble_error_t legacy_pairing_oob_data_request_reply(
virtual ble_error_t legacy_pairing_oob_request_reply(
connection_handle_t connection,
const oob_tk_t &oob_data
);
@ -295,12 +295,26 @@ public:
);
/**
* @see ::ble::pal::SecurityManager::oob_data_verified
* @see ::ble::pal::SecurityManager::generate_secure_connections_oob
*/
virtual ble_error_t oob_data_verified(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random
virtual ble_error_t generate_secure_connections_oob(
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_connectinos_oob_present
*/
virtual bool is_secure_connectinos_oob_present(
const address_t &address
);
// singleton of the ARM Cordio Security Manager

View File

@ -364,7 +364,7 @@ ble_error_t CordioSecurityManager::passkey_request_reply(
return BLE_ERROR_NONE;
}
ble_error_t CordioSecurityManager::legacy_pairing_oob_data_request_reply(
ble_error_t CordioSecurityManager::legacy_pairing_oob_request_reply(
connection_handle_t connection,
const oob_tk_t &oob_data
) {
@ -394,15 +394,26 @@ ble_error_t CordioSecurityManager::send_keypress_notification(
return BLE_ERROR_NONE;
}
ble_error_t CordioSecurityManager::oob_data_verified(
connection_handle_t connection,
const oob_lesc_value_t &local_random,
const oob_lesc_value_t &peer_random
ble_error_t CordioSecurityManager::generate_secure_connections_oob(
connection_handle_t connection
) {
// FIXME:
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
) {
return BLE_ERROR_NOT_IMPLEMENTED;
}
bool CordioSecurityManager::is_secure_connectinos_oob_present(
const address_t &address
) {
return false;
}
CordioSecurityManager& CordioSecurityManager::get_security_manager()
{
static CordioSecurityManager _security_manager;