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), _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL),
_pairing_authorisation_required(false), _pairing_authorisation_required(false),
_legacy_pairing_allowed(true), _legacy_pairing_allowed(true),
_master_sends_keys(false), _master_sends_keys(false) {
_public_keys_generated(false) {
_pal.set_event_handler(this); _pal.set_event_handler(this);
} }
@ -321,17 +320,6 @@ private:
const csrk_t *csrk 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. * Updates the entry for the connection with OOB data presence.
* *
@ -341,26 +329,6 @@ private:
connection_handle_t connection 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 * Set the MITM protection setting on the database entry
* *
@ -477,13 +445,6 @@ private:
bool _pairing_authorisation_required; bool _pairing_authorisation_required;
bool _legacy_pairing_allowed; bool _legacy_pairing_allowed;
bool _master_sends_keys; 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; static const size_t MAX_CONTROL_BLOCKS = 5;
ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS]; ControlBlock_t _control_blocks[MAX_CONTROL_BLOCKS];
@ -593,25 +554,18 @@ public:
connection_handle_t connection 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( virtual void on_secure_connections_oob_generated(
connection_handle_t connection, const address_t &local_address,
const public_key_coord_t &peer_public_key_x, const oob_lesc_value_t &random,
const public_key_coord_t &peer_public_key_y const oob_confirm_t &confirm
); );
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Keys // 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 /** @copydoc ble::pal::SecurityManager::on_secure_connections_ltk_generated
*/ */
virtual void on_secure_connections_ltk_generated( virtual void on_secure_connections_ltk_generated(

View File

@ -240,24 +240,6 @@ public:
_local_csrk = csrk; _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 */ /* list management */
virtual entry_handle_t open_entry( virtual entry_handle_t open_entry(
@ -362,8 +344,6 @@ private:
entry_t _entries[MAX_ENTRIES]; entry_t _entries[MAX_ENTRIES];
SecurityEntryIdentity_t _local_identity; SecurityEntryIdentity_t _local_identity;
csrk_t _local_csrk; csrk_t _local_csrk;
public_key_coord_t _public_key_x;
public_key_coord_t _public_key_y;
}; };
} /* namespace pal */ } /* namespace pal */

View File

@ -371,7 +371,7 @@ public:
* Request OOB data from the user application. * Request OOB data from the user application.
* *
* @param[in] connection connection handle * @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. * or a cancellation of the procedure.
*/ */
virtual void on_legacy_pairing_oob_request( virtual void on_legacy_pairing_oob_request(
@ -379,32 +379,24 @@ public:
) = 0; ) = 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] address address of the local device
* @param[in] public_key_y newly generated public key (y coordinate) * @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( virtual void on_secure_connections_oob_generated(
connection_handle_t connection, const address_t &local_address,
const public_key_coord_t &peer_public_key_x, const oob_lesc_value_t &random,
const public_key_coord_t &peer_public_key_y const oob_confirm_t &confirm
) = 0; ) = 0;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Keys // 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 * 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 * @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.6.5
@ -863,14 +855,6 @@ public:
const csrk_t &csrk const csrk_t &csrk
) = 0; ) = 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 // Authentication
// //
@ -931,7 +915,7 @@ public:
* @param[in] oob_data pointer to out of band data * @param[in] oob_data pointer to out of band data
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure * @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, connection_handle_t connection,
const oob_tk_t &oob_data const oob_tk_t &oob_data
) = 0; ) = 0;
@ -963,20 +947,38 @@ public:
) = 0; ) = 0;
/** /**
* Notify the stack that the OOB data has been verified and supply the peer's random number. * Generate local OOB data to be sent to the application which sends it to the peer.
* If the verification failed this will not be called and cancel_pairing will be called instead.
* *
* @param[in] connection connection handle * @param[in] connectionHandle Handle to identify the connection.
* @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
*/ */
virtual ble_error_t oob_data_verified( virtual ble_error_t generate_secure_connections_oob(
connection_handle_t connection, connection_handle_t connection
const oob_lesc_value_t &local_random, ) = 0;
const oob_lesc_value_t &peer_random
/**
* 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; ) = 0;
/* Entry points for the underlying stack to report events back to the user. */ /* 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; 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 */ /* list management */
/** /**

View File

@ -17,9 +17,6 @@
#include "ble/SecurityManager.h" #include "ble/SecurityManager.h"
#include "ble/pal/PalSecurityManager.h" #include "ble/pal/PalSecurityManager.h"
#include "ble/generic/GenericSecurityManager.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::advertising_peer_address_type_t;
using ble::pal::AuthenticationMask; using ble::pal::AuthenticationMask;
@ -71,14 +68,11 @@ ble_error_t GenericSecurityManager::init(
_connection_monitor.set_connection_event_handler(this); _connection_monitor.set_connection_event_handler(this);
_pal.set_event_handler(this); _pal.set_event_handler(this);
_pal.generate_public_key();
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
ble_error_t GenericSecurityManager::reset(void) { ble_error_t GenericSecurityManager::reset(void) {
_db.sync(); _db.sync();
_public_keys_generated = false;
SecurityManager::reset(); SecurityManager::reset();
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
@ -519,11 +513,7 @@ ble_error_t GenericSecurityManager::setOOBDataUsage(
cb->attempt_oob = useOOB; cb->attempt_oob = useOOB;
cb->oob_mitm_protection = OOBProvidesMITM; cb->oob_mitm_protection = OOBProvidesMITM;
#if defined(MBEDTLS_CMAC_C) _pal.generate_secure_connections_oob(connection);
if (_public_keys_generated) {
generate_secure_connections_oob(connection);
}
#endif
return BLE_ERROR_NONE; return BLE_ERROR_NONE;
} }
@ -562,7 +552,7 @@ ble_error_t GenericSecurityManager::legacyPairingOobReceived(
return BLE_ERROR_INVALID_PARAM; 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; return BLE_ERROR_NONE;
} }
@ -573,10 +563,7 @@ ble_error_t GenericSecurityManager::oobReceived(
const oob_confirm_t *confirm const oob_confirm_t *confirm
) { ) {
if (address && random && confirm) { if (address && random && confirm) {
_peer_sc_oob_address = *address; return _pal.secure_connections_oob_received(*address, *random, *confirm);
_peer_sc_oob_random = *random;
_peer_sc_oob_confirm = *confirm;
return BLE_ERROR_NONE;
} }
return BLE_ERROR_INVALID_PARAM; 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) { void GenericSecurityManager::update_oob_presence(connection_handle_t connection) {
ControlBlock_t *cb = get_control_block(connection); ControlBlock_t *cb = get_control_block(connection);
if (!cb) { if (!cb) {
@ -743,45 +696,10 @@ void GenericSecurityManager::update_oob_presence(connection_handle_t connection)
cb->oob_present = cb->attempt_oob; cb->oob_present = cb->attempt_oob;
if (_default_authentication.get_secure_connections()) { if (_default_authentication.get_secure_connections()) {
cb->oob_present = false; cb->oob_present = _pal.is_secure_connectinos_oob_present(cb->peer_address);
#if defined(MBEDTLS_CMAC_C)
if (cb->peer_address == _peer_sc_oob_address) {
cb->oob_present = true;
}
#endif
} }
} }
#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) { void GenericSecurityManager::set_mitm_performed(connection_handle_t connection, bool enable) {
ControlBlock_t *cb = get_control_block(connection); ControlBlock_t *cb = get_control_block(connection);
if (cb) { if (cb) {
@ -1031,44 +949,18 @@ void GenericSecurityManager::on_legacy_pairing_oob_request(connection_handle_t c
eventHandler->legacyPairingOobRequest(connection); eventHandler->legacyPairingOobRequest(connection);
} }
void GenericSecurityManager::on_oob_data_verification_request( void GenericSecurityManager::on_secure_connections_oob_generated(
connection_handle_t connection, const address_t &local_address,
const public_key_coord_t &peer_public_key_x, const oob_lesc_value_t &random,
const public_key_coord_t &peer_public_key_y const oob_confirm_t &confirm
) { ) {
#if defined(MBEDTLS_CMAC_C) eventHandler->oobGenerated(&local_address, &random, &confirm);
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
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Keys // 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( void GenericSecurityManager::on_secure_connections_ltk_generated(
connection_handle_t connection, connection_handle_t connection,
const ltk_t &ltk 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, connection_handle_t connection,
const oob_tk_t &oob_data 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( virtual ble_error_t generate_secure_connections_oob(
connection_handle_t connection, connection_handle_t connection
const oob_lesc_value_t &local_random, );
const oob_lesc_value_t &peer_random
/**
* @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 // singleton of the ARM Cordio Security Manager

View File

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