diff --git a/features/FEATURE_BLE/ble/generic/GenericGattClient.h b/features/FEATURE_BLE/ble/generic/GenericGattClient.h index f0a8462ff9..7dbb0e185d 100644 --- a/features/FEATURE_BLE/ble/generic/GenericGattClient.h +++ b/features/FEATURE_BLE/ble/generic/GenericGattClient.h @@ -20,6 +20,7 @@ #include #include "ble/GattClient.h" #include "ble/pal/PalGattClient.h" +#include "ble/pal/SigningEventMonitor.h" // IMPORTANT: private header. Not part of the public interface. @@ -31,7 +32,8 @@ namespace generic { * It requires a pal::GattClient injected at construction site. * @attention: Not part of the public interface of BLE API. */ -class GenericGattClient : public GattClient { +class GenericGattClient : public GattClient, + public pal::SigningEventMonitor { public: /** * Create a GenericGattClient from a pal::GattClient @@ -114,6 +116,11 @@ public: */ virtual ble_error_t reset(void); + /** + * @see ble::pal::SigningEventMonitor::set_signing_event_handler + */ + virtual void set_signing_event_handler(pal::SigningEventMonitor::EventHandler *signing_event_handler); + private: struct ProcedureControlBlock; struct DiscoveryControlBlock; @@ -136,6 +143,7 @@ private: pal::GattClient* const _pal_client; ServiceDiscovery::TerminationCallback_t _termination_callback; + pal::SigningEventMonitor::EventHandler* _signing_event_handler; mutable ProcedureControlBlock* control_blocks; bool _is_reseting; }; diff --git a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h index c7ea499b69..315627afdc 100644 --- a/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h +++ b/features/FEATURE_BLE/ble/generic/GenericSecurityManager.h @@ -22,6 +22,7 @@ #include "ble/pal/SecurityDb.h" #include "platform/Callback.h" #include "ble/pal/ConnectionEventMonitor.h" +#include "ble/pal/SigningEventMonitor.h" #include "ble/generic/GenericGap.h" #include "ble/pal/PalSecurityManager.h" @@ -32,7 +33,8 @@ typedef SecurityManager::SecurityIOCapabilities_t SecurityIOCapabilities_t; class GenericSecurityManager : public SecurityManager, public pal::SecurityManager::EventHandler, - public pal::ConnectionEventMonitor::EventHandler { + public pal::ConnectionEventMonitor::EventHandler, + public pal::SigningEventMonitor::EventHandler { public: typedef ble::pal::SecurityDistributionFlags_t SecurityDistributionFlags_t; typedef ble::pal::SecurityEntryKeys_t SecurityEntryKeys_t; @@ -234,10 +236,12 @@ public: GenericSecurityManager( pal::SecurityManager &palImpl, pal::SecurityDb &dbImpl, - pal::ConnectionEventMonitor &connMonitorImpl + pal::ConnectionEventMonitor &connMonitorImpl, + pal::SigningEventMonitor &signingMonitorImpl ) : _pal(palImpl), _db(dbImpl), _connection_monitor(connMonitorImpl), + _signing_monitor(signingMonitorImpl), _default_authentication(0), _default_key_distribution(pal::KeyDistribution::KEY_DISTRIBUTION_ALL), _pairing_authorisation_required(false), @@ -467,6 +471,7 @@ private: pal::SecurityManager &_pal; pal::SecurityDb &_db; pal::ConnectionEventMonitor &_connection_monitor; + pal::SigningEventMonitor &_signing_monitor; /* OOB data */ address_t _oob_local_address; @@ -547,6 +552,10 @@ public: connection_handle_t connection ); + /** @copydoc ble::pal::SecurityManager::on_signed_write + */ + virtual void on_signed_write(); + /** @copydoc ble::pal::SecurityManager::on_slave_security_request */ virtual void on_slave_security_request( diff --git a/features/FEATURE_BLE/ble/pal/AttClient.h b/features/FEATURE_BLE/ble/pal/AttClient.h index 061b19b6a1..56bd1a2f06 100644 --- a/features/FEATURE_BLE/ble/pal/AttClient.h +++ b/features/FEATURE_BLE/ble/pal/AttClient.h @@ -485,7 +485,6 @@ struct AttClient { * request to. * @param attribute_handle Handle of the attribute to write. * @param value Value to write. It can't be longer than (mtu - 15). - * @param sign_counter Signed write counter to use for this command. * * @note the authentication signature to send with this request is * computed by the implementation following the rules defined in BLUETOOTH @@ -499,8 +498,7 @@ struct AttClient { virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h index e9b4d7d75d..d99a55e497 100644 --- a/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h +++ b/features/FEATURE_BLE/ble/pal/AttClientToGattClientAdapter.h @@ -221,14 +221,12 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { return _client.signed_write_command( connection_handle, characteristic_value_handle, - value, - sign_counter + value ); } diff --git a/features/FEATURE_BLE/ble/pal/PalGattClient.h b/features/FEATURE_BLE/ble/pal/PalGattClient.h index 4dfdb31b6a..2152c428f4 100644 --- a/features/FEATURE_BLE/ble/pal/PalGattClient.h +++ b/features/FEATURE_BLE/ble/pal/PalGattClient.h @@ -455,15 +455,13 @@ public: * @param connection_handle The handle of the connection to send this request to. * @param attribute_handle Handle of the attribute to write. * @param value The value to write. - * @param sign_counter Signed write counter to use for this command. * * @return BLE_ERROR_NONE or an appropriate error. */ virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) = 0; /** diff --git a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h index c0ffc4aa21..fe942a0aa8 100644 --- a/features/FEATURE_BLE/ble/pal/PalSecurityManager.h +++ b/features/FEATURE_BLE/ble/pal/PalSecurityManager.h @@ -280,27 +280,6 @@ public: connection_handle_t connection ) = 0; - /** - * Set new signed write peer counter. - * - * @param[in] connection connection handle - * @param[in] sign_coutner counter received from peer - */ - virtual void on_signed_write_received( - connection_handle_t connection, - uint32_t sign_coutner - ) = 0; - - /** - * Indicate that signed data was rejected due to verification failure. This could - * be due to an invalid CSRK key. - * - * @param[in] connection connection handle - */ - virtual void on_signed_write_verification_failure( - connection_handle_t connection - ) = 0; - /** * Ask the stack to evaluate the security request received from the slave. * This might result in the stack enabling encryption, or pairing/re-pairing. @@ -879,11 +858,13 @@ public: /** * Set the local CSRK. * - * @param[in] csrk signing key + * @param[in] csrk local signing key + * @param[in] sign_counter local signing counter * @return BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_csrk( - const csrk_t &csrk + const csrk_t &csrk, + uint32_t sign_counter ) = 0; /** @@ -891,6 +872,8 @@ public: * * @param[in] connection connection handle * @param[in] csrk signing key + * @param[in] authenticated is the CSRK authenticated + * @param[in] sign_counter signing counter * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure */ virtual ble_error_t set_peer_csrk( diff --git a/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h new file mode 100644 index 0000000000..bc6392c8be --- /dev/null +++ b/features/FEATURE_BLE/ble/pal/SigningEventMonitor.h @@ -0,0 +1,74 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017-2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_BLE_SIGNING_EVENT_MONITOR +#define MBED_BLE_SIGNING_EVENT_MONITOR + +#include "ble/BLETypes.h" + +namespace ble { +namespace pal { + +/** + * Implemented by classes that need to be notified of signing events. + * Notification is done by calling functions in the passed in event handler + */ +class SigningEventMonitor { +public: + /** + * Implemented by classes that are reacting to signing events. + */ + class EventHandler { + public: + /** + * Set new signed write peer counter. + * + * @param[in] connection connection handle + * @param[in] sign_coutner counter received from peer + */ + virtual void on_signed_write_received( + connection_handle_t connection, + uint32_t sign_coutner + ) = 0; + + /** + * Indicate that signed data was rejected due to verification failure. This could + * be due to an invalid CSRK key. + * + * @param[in] connection connection handle + */ + virtual void on_signed_write_verification_failure( + connection_handle_t connection + ) = 0; + + /** + * Notify a new signed write cmd was executed. + */ + virtual void on_signed_write() = 0; + }; + + /** + * Register a handler for singing events to be used internally and serviced first. + * + * @param[in] signing_event_handler Event handler being registered. + */ + virtual void set_signing_event_handler(EventHandler *signing_event_handler) = 0; +}; + +} // namespace pal +} // namespace ble + +#endif /* MBED_BLE_SIGNING_EVENT_MONITOR */ diff --git a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp index 83c577f259..088e120dd6 100644 --- a/features/FEATURE_BLE/source/generic/GenericGattClient.cpp +++ b/features/FEATURE_BLE/source/generic/GenericGattClient.cpp @@ -936,6 +936,7 @@ struct GenericGattClient::DescriptorDiscoveryControlBlock : public ProcedureCont GenericGattClient::GenericGattClient(pal::GattClient* pal_client) : _pal_client(pal_client), _termination_callback(), + _signing_event_handler(NULL), control_blocks(NULL), _is_reseting(false) { _pal_client->when_server_message_received( @@ -1097,14 +1098,15 @@ ble_error_t GenericGattClient::write( if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) { return BLE_ERROR_PARAM_OUT_OF_RANGE; } - GenericSecurityManager* sm = (GenericSecurityManager*)(&createBLEInstance()->getSecurityManager()); - const uint32_t sign_counter = sm->get_next_sign_counter(); - return _pal_client->signed_write_without_response( + ble_error_t status = _pal_client->signed_write_without_response( connection_handle, attribute_handle, - make_const_ArrayView(value, length), - sign_counter + make_const_ArrayView(value, length) ); + if (_signing_event_handler && (status == BLE_ERROR_NONE)) { + _signing_event_handler->on_signed_write(); + } + return status; } else { uint8_t* data = NULL; @@ -1257,6 +1259,12 @@ ble_error_t GenericGattClient::reset(void) { return BLE_ERROR_NONE; } +void GenericGattClient::set_signing_event_handler( + EventHandler *signing_event_handler +) { + _signing_event_handler = signing_event_handler; +} + void GenericGattClient::on_termination(Gap::Handle_t connection_handle) { if (_termination_callback) { _termination_callback(connection_handle); diff --git a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp index b7ef84330f..dd37331504 100644 --- a/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp +++ b/features/FEATURE_BLE/source/generic/GenericSecurityManager.cpp @@ -71,6 +71,7 @@ ble_error_t GenericSecurityManager::init( } _connection_monitor.set_connection_event_handler(this); + _signing_monitor.set_signing_event_handler(this); _pal.set_event_handler(this); return BLE_ERROR_NONE; @@ -640,7 +641,8 @@ ble_error_t GenericSecurityManager::oobReceived( ble_error_t GenericSecurityManager::init_signing() { const csrk_t *pcsrk = _db.get_local_csrk(); - _local_sign_counter = _db.get_local_sign_counter(); + uint32_t local_sign_counter = _db.get_local_sign_counter(); + if (!pcsrk) { csrk_t csrk; @@ -651,9 +653,10 @@ ble_error_t GenericSecurityManager::init_signing() { pcsrk = &csrk; _db.set_local_csrk(csrk); - _db.set_local_sign_counter(_local_sign_counter); + _db.set_local_sign_counter(local_sign_counter); } - return _pal.set_csrk(*pcsrk); + + return _pal.set_csrk(*pcsrk, local_sign_counter); } ble_error_t GenericSecurityManager::get_random_data(uint8_t *buffer, size_t size) { @@ -947,6 +950,7 @@ void GenericSecurityManager::on_pairing_completed(connection_handle_t connection void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection) { (void)connection; } + void GenericSecurityManager::on_signed_write_received( connection_handle_t connection, uint32_t sign_counter @@ -983,6 +987,10 @@ void GenericSecurityManager::on_signed_write_verification_failure( } } +void GenericSecurityManager::on_signed_write() { + _db.set_local_sign_counter(_db.get_local_sign_counter() + 1); +} + void GenericSecurityManager::on_slave_security_request( connection_handle_t connection, AuthenticationMask authentication diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h index 016b866add..eb64bafaee 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalAttClient.h @@ -211,13 +211,12 @@ public: virtual ble_error_t signed_write_command( connection_handle_t connection_handle, attribute_handle_t attribute_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { AttcSignedWriteCmd( connection_handle, attribute_handle, - sign_counter, + /*TODO: get sign counter from cordio sm */0, value.size(), const_cast(value.data()) ); diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h index 02b8522c27..c9bc5bc779 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/CordioPalSecurityManager.h @@ -237,7 +237,10 @@ public: /** * @see ::ble::pal::SecurityManager::set_csrk */ - virtual ble_error_t set_csrk(const csrk_t &csrk); + virtual ble_error_t set_csrk( + const csrk_t &csrk, + uint32_t sign_counter + ); /** * @see ::ble::pal::SecurityManager::set_peer_csrk @@ -321,6 +324,7 @@ public: private: bool _use_default_passkey; passkey_num_t _default_passkey; + uint32_t _local_sign_counter; bool _lesc_keys_generated; uint8_t _public_key_x[SEC_ECC_KEY_LEN]; }; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp index 93a5327012..e6d01ef6b3 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioBLE.cpp @@ -219,10 +219,14 @@ const SecurityManager& BLE::getSecurityManager() const { static pal::MemorySecurityDb m_db; pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager(); + + BLE *self = const_cast(this); + static generic::GenericSecurityManager m_instance( m_pal, m_db, - const_cast(getGenericGap()) + const_cast(getGenericGap()), + static_cast(self->getGattClient()) ); return m_instance; diff --git a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp index 9136053fca..6bf678c5d5 100644 --- a/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp +++ b/features/FEATURE_BLE/targets/TARGET_CORDIO/source/CordioPalSecurityManager.cpp @@ -31,6 +31,7 @@ CordioSecurityManager::CordioSecurityManager() : ::ble::pal::SecurityManager(), _use_default_passkey(false), _default_passkey(0), + _local_sign_counter(0), _lesc_keys_generated(false), _public_key_x() { @@ -267,8 +268,11 @@ ble_error_t CordioSecurityManager::set_irk(const irk_t& irk) return BLE_ERROR_NONE; } -ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk) -{ +ble_error_t CordioSecurityManager::set_csrk( + const csrk_t& csrk, + uint32_t sign_counter +) { + _local_sign_counter = sign_counter; DmSecSetLocalCsrk(const_cast(csrk.data())); return BLE_ERROR_NONE; } diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp index 80d350c30f..cba1ea60d4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.cpp @@ -300,8 +300,7 @@ ble_error_t nRF5XGattClient::write_without_response( ble_error_t nRF5XGattClient::signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ) { ble_gattc_write_params_t write_params = { BLE_GATT_OP_SIGN_WRITE_CMD, diff --git a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h index 20b20296de..ede03ce3f4 100644 --- a/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h +++ b/features/FEATURE_BLE/targets/TARGET_NORDIC/TARGET_NRF5/source/nRF5XPalGattClient.h @@ -153,8 +153,7 @@ public: virtual ble_error_t signed_write_without_response( connection_handle_t connection_handle, attribute_handle_t characteristic_value_handle, - const ArrayView& value, - uint32_t sign_counter + const ArrayView& value ); /**