mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #26 from paul-szczepanek-arm/signing
signing integration between gatt and smpull/6932/head
commit
0833827460
|
@ -116,6 +116,15 @@ public:
|
||||||
* The server does not acknowledge the status of the operation.
|
* The server does not acknowledge the status of the operation.
|
||||||
*/
|
*/
|
||||||
GATT_OP_WRITE_CMD = 0x02,
|
GATT_OP_WRITE_CMD = 0x02,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signed Write command.
|
||||||
|
*
|
||||||
|
* It is used to request the server to write the value of an attribute
|
||||||
|
* using a signed packet. The server does not acknowledge the status
|
||||||
|
* of the operation.
|
||||||
|
*/
|
||||||
|
GATT_OP_SIGNED_WRITE_CMD = 0x03
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -322,13 +322,24 @@ private:
|
||||||
* Returns the CSRK for the connection. Called by the security db.
|
* Returns the CSRK for the connection. Called by the security db.
|
||||||
*
|
*
|
||||||
* @param[in] connectionHandle Handle to identify the connection.
|
* @param[in] connectionHandle Handle to identify the connection.
|
||||||
* @param[in] entryKeys security entry containing keys.
|
* @param[in] csrk connection signature resolving key.
|
||||||
*/
|
*/
|
||||||
void return_csrk_cb(
|
void return_csrk_cb(
|
||||||
pal::SecurityDb::entry_handle_t connection,
|
pal::SecurityDb::entry_handle_t connection,
|
||||||
const csrk_t *csrk
|
const csrk_t *csrk
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the peer CSRK for the connection. Called by the security db.
|
||||||
|
*
|
||||||
|
* @param[in] connectionHandle Handle to identify the connection.
|
||||||
|
* @param[in] csrk connection signature resolving key.
|
||||||
|
*/
|
||||||
|
void set_peer_csrk_cb(
|
||||||
|
pal::SecurityDb::entry_handle_t connection,
|
||||||
|
const csrk_t *csrk
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the entry for the connection with OOB data presence.
|
* Updates the entry for the connection with OOB data presence.
|
||||||
*
|
*
|
||||||
|
@ -443,6 +454,8 @@ private:
|
||||||
uint8_t oob_mitm_protection:1;
|
uint8_t oob_mitm_protection:1;
|
||||||
uint8_t oob_present:1;
|
uint8_t oob_present:1;
|
||||||
uint8_t legacy_pairing_oob_request_pending:1;
|
uint8_t legacy_pairing_oob_request_pending:1;
|
||||||
|
|
||||||
|
uint8_t csrk_failures:2;
|
||||||
};
|
};
|
||||||
|
|
||||||
pal::SecurityManager &_pal;
|
pal::SecurityManager &_pal;
|
||||||
|
@ -513,6 +526,12 @@ public:
|
||||||
connection_handle_t connection
|
connection_handle_t connection
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/** @copydoc ble::pal::SecurityManager::on_signature_verification_failure
|
||||||
|
*/
|
||||||
|
virtual void on_signature_verification_failure(
|
||||||
|
connection_handle_t connection
|
||||||
|
);
|
||||||
|
|
||||||
/** @copydoc ble::pal::SecurityManager::on_slave_security_request
|
/** @copydoc ble::pal::SecurityManager::on_slave_security_request
|
||||||
*/
|
*/
|
||||||
virtual void on_slave_security_request(
|
virtual void on_slave_security_request(
|
||||||
|
|
|
@ -280,6 +280,16 @@ public:
|
||||||
connection_handle_t connection
|
connection_handle_t connection
|
||||||
) = 0;
|
) = 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_signature_verification_failure(
|
||||||
|
connection_handle_t connection
|
||||||
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask the stack to evaluate the security request received from the slave.
|
* Ask the stack to evaluate the security request received from the slave.
|
||||||
* This might result in the stack enabling encryption, or pairing/re-pairing.
|
* This might result in the stack enabling encryption, or pairing/re-pairing.
|
||||||
|
@ -865,6 +875,19 @@ public:
|
||||||
const csrk_t &csrk
|
const csrk_t &csrk
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the peer CSRK for particular connection.
|
||||||
|
*
|
||||||
|
* @param[in] connection connection handle
|
||||||
|
* @param[in] csrk signing key
|
||||||
|
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure
|
||||||
|
*/
|
||||||
|
virtual ble_error_t set_peer_csrk(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const csrk_t &csrk,
|
||||||
|
bool authenticated
|
||||||
|
) = 0;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Authentication
|
// Authentication
|
||||||
//
|
//
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <ble/DiscoveredCharacteristic.h>
|
#include <ble/DiscoveredCharacteristic.h>
|
||||||
#include "ble/generic/GenericGattClient.h"
|
#include "ble/generic/GenericGattClient.h"
|
||||||
#include "ble/blecommon.h"
|
#include "ble/blecommon.h"
|
||||||
|
#include "ble/BLEInstanceBase.h"
|
||||||
|
#include "ble/generic/GenericSecurityManager.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
using ble::pal::AttServerMessage;
|
using ble::pal::AttServerMessage;
|
||||||
|
@ -38,6 +40,11 @@ using ble::pal::AttHandleValueIndication;
|
||||||
using ble::pal::AttHandleValueNotification;
|
using ble::pal::AttHandleValueNotification;
|
||||||
using ble::pal::AttFindInformationResponse;
|
using ble::pal::AttFindInformationResponse;
|
||||||
|
|
||||||
|
#define PREPARE_WRITE_HEADER_LENGTH 5
|
||||||
|
#define WRITE_HEADER_LENGTH 3
|
||||||
|
#define CMAC_LENGTH 8
|
||||||
|
#define MAC_COUNTER_LENGTH 4
|
||||||
|
|
||||||
namespace ble {
|
namespace ble {
|
||||||
namespace generic {
|
namespace generic {
|
||||||
|
|
||||||
|
@ -1074,67 +1081,77 @@ ble_error_t GenericGattClient::write(
|
||||||
return BLE_ERROR_INVALID_STATE;
|
return BLE_ERROR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t mtu = get_mtu(connection_handle);
|
uint16_t mtu = get_mtu(connection_handle);
|
||||||
|
|
||||||
if (cmd == GattClient::GATT_OP_WRITE_CMD) {
|
if (cmd == GattClient::GATT_OP_WRITE_CMD) {
|
||||||
if (length > (uint16_t)(mtu - 3)) {
|
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||||
}
|
}
|
||||||
return _pal_client->write_without_response(
|
return _pal_client->write_without_response(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
make_const_ArrayView(value, length)
|
make_const_ArrayView(value, length)
|
||||||
);
|
);
|
||||||
} else {
|
} else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) {
|
||||||
uint8_t* data = NULL;
|
/*TODO check encryption status */
|
||||||
|
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH - CMAC_LENGTH - MAC_COUNTER_LENGTH)) {
|
||||||
|
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||||
|
}
|
||||||
|
return _pal_client->signed_write_without_response(
|
||||||
|
connection_handle,
|
||||||
|
attribute_handle,
|
||||||
|
make_const_ArrayView(value, length)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
uint8_t* data = NULL;
|
||||||
|
|
||||||
if (length > (uint16_t)(mtu - 3)) {
|
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||||
data = (uint8_t*) malloc(length);
|
data = (uint8_t*) malloc(length);
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
return BLE_ERROR_NO_MEM;
|
return BLE_ERROR_NO_MEM;
|
||||||
}
|
}
|
||||||
memcpy(data, value, length);
|
memcpy(data, value, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock(
|
WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
data,
|
data,
|
||||||
length
|
length
|
||||||
);
|
);
|
||||||
|
|
||||||
if (write_pcb == NULL) {
|
if (write_pcb == NULL) {
|
||||||
free(data);
|
free(data);
|
||||||
return BLE_ERROR_NO_MEM;
|
return BLE_ERROR_NO_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_control_block(write_pcb);
|
insert_control_block(write_pcb);
|
||||||
|
|
||||||
ble_error_t err = BLE_ERROR_UNSPECIFIED;
|
ble_error_t err = BLE_ERROR_UNSPECIFIED;
|
||||||
if (data) {
|
if (data) {
|
||||||
err = _pal_client->queue_prepare_write(
|
err = _pal_client->queue_prepare_write(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
make_const_ArrayView(value, mtu - 5),
|
make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH),
|
||||||
/* offset */ 0
|
/* offset */0
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
err = _pal_client->write_attribute(
|
err = _pal_client->write_attribute(
|
||||||
connection_handle,
|
connection_handle,
|
||||||
attribute_handle,
|
attribute_handle,
|
||||||
make_const_ArrayView(value, length)
|
make_const_ArrayView(value, length)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
remove_control_block(write_pcb);
|
remove_control_block(write_pcb);
|
||||||
delete write_pcb;
|
delete write_pcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericGattClient::onServiceDiscoveryTermination(
|
void GenericGattClient::onServiceDiscoveryTermination(
|
||||||
|
|
|
@ -140,14 +140,10 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio
|
||||||
* use when roles are changed */
|
* use when roles are changed */
|
||||||
if (_master_sends_keys) {
|
if (_master_sends_keys) {
|
||||||
initiator_distribution = _default_key_distribution;
|
initiator_distribution = _default_key_distribution;
|
||||||
}
|
/* override default if requested */
|
||||||
|
if (cb->signing_override_default) {
|
||||||
/* override default if requested */
|
initiator_distribution.set_signing(cb->signing_requested);
|
||||||
if (cb->signing_override_default) {
|
}
|
||||||
initiator_distribution.set_signing(cb->signing_requested);
|
|
||||||
} else {
|
|
||||||
/* because _master_sends_keys might be false so we need to set this */
|
|
||||||
initiator_distribution.set_signing(_default_key_distribution.get_signing());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyDistribution responder_distribution(_default_key_distribution);
|
KeyDistribution responder_distribution(_default_key_distribution);
|
||||||
|
@ -312,19 +308,27 @@ ble_error_t GenericSecurityManager::enableSigning(
|
||||||
return BLE_ERROR_INVALID_PARAM;
|
return BLE_ERROR_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
cb->signing_requested = enabled;
|
cb->signing_override_default = true;
|
||||||
cb->signing_override_default = false;
|
|
||||||
|
|
||||||
if (cb->encrypted) {
|
if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) {
|
||||||
return BLE_ERROR_INVALID_STATE;
|
cb->signing_requested = true;
|
||||||
}
|
if (cb->csrk_stored) {
|
||||||
if (!cb->csrk_stored && cb->signing_requested) {
|
/* used the stored ones when available */
|
||||||
init_signing();
|
_db.get_entry_peer_csrk(
|
||||||
if (cb->is_master) {
|
mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
|
||||||
return requestPairing(connection);
|
cb->db_entry
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return slave_security_request(connection);
|
/* create keys if needed and exchange them */
|
||||||
|
init_signing();
|
||||||
|
if (cb->is_master) {
|
||||||
|
return requestPairing(connection);
|
||||||
|
} else {
|
||||||
|
return slave_security_request(connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
cb->signing_requested = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
|
@ -729,6 +733,22 @@ void GenericSecurityManager::set_ltk_cb(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericSecurityManager::set_peer_csrk_cb(
|
||||||
|
pal::SecurityDb::entry_handle_t db_entry,
|
||||||
|
const csrk_t *csrk
|
||||||
|
) {
|
||||||
|
ControlBlock_t *cb = get_control_block(db_entry);
|
||||||
|
if (!cb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pal.set_peer_csrk(
|
||||||
|
cb->connection,
|
||||||
|
*csrk,
|
||||||
|
cb->csrk_mitm_protected
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::return_csrk_cb(
|
void GenericSecurityManager::return_csrk_cb(
|
||||||
pal::SecurityDb::entry_handle_t db_entry,
|
pal::SecurityDb::entry_handle_t db_entry,
|
||||||
const csrk_t *csrk
|
const csrk_t *csrk
|
||||||
|
@ -808,6 +828,17 @@ void GenericSecurityManager::on_connected(
|
||||||
if (dist_flags) {
|
if (dist_flags) {
|
||||||
*static_cast<pal::SecurityDistributionFlags_t*>(cb) = *dist_flags;
|
*static_cast<pal::SecurityDistributionFlags_t*>(cb) = *dist_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool signing = cb->signing_override_default ?
|
||||||
|
cb->signing_requested :
|
||||||
|
_default_key_distribution.get_signing();
|
||||||
|
|
||||||
|
if (signing && cb->csrk_stored) {
|
||||||
|
_db.get_entry_peer_csrk(
|
||||||
|
mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
|
||||||
|
cb->db_entry
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::on_disconnected(
|
void GenericSecurityManager::on_disconnected(
|
||||||
|
@ -912,6 +943,31 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t connection
|
||||||
(void)connection;
|
(void)connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericSecurityManager::on_signature_verification_failure(
|
||||||
|
connection_handle_t connection
|
||||||
|
) {
|
||||||
|
ControlBlock_t *cb = get_control_block(connection);
|
||||||
|
if (!cb) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool signing = cb->signing_override_default ?
|
||||||
|
cb->signing_requested :
|
||||||
|
_default_key_distribution.get_signing();
|
||||||
|
|
||||||
|
if (signing) {
|
||||||
|
cb->csrk_failures++;
|
||||||
|
if (cb->csrk_failures == 3) {
|
||||||
|
cb->csrk_failures = 0;
|
||||||
|
if (cb->is_master) {
|
||||||
|
requestPairing(connection);
|
||||||
|
} else {
|
||||||
|
slave_security_request(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GenericSecurityManager::on_slave_security_request(
|
void GenericSecurityManager::on_slave_security_request(
|
||||||
connection_handle_t connection,
|
connection_handle_t connection,
|
||||||
AuthenticationMask authentication
|
AuthenticationMask authentication
|
||||||
|
@ -1228,7 +1284,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
|
||||||
attempt_oob(false),
|
attempt_oob(false),
|
||||||
oob_mitm_protection(false),
|
oob_mitm_protection(false),
|
||||||
oob_present(false),
|
oob_present(false),
|
||||||
legacy_pairing_oob_request_pending(false) { }
|
legacy_pairing_oob_request_pending(false),
|
||||||
|
csrk_failures(0) { }
|
||||||
|
|
||||||
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
|
void GenericSecurityManager::on_ltk_request(connection_handle_t connection)
|
||||||
{
|
{
|
||||||
|
|
|
@ -239,6 +239,15 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ble_error_t set_csrk(const csrk_t &csrk);
|
virtual ble_error_t set_csrk(const csrk_t &csrk);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ::ble::pal::SecurityManager::set_peer_csrk
|
||||||
|
*/
|
||||||
|
virtual ble_error_t set_peer_csrk(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const csrk_t &csrk,
|
||||||
|
bool authenticated
|
||||||
|
);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Authentication
|
// Authentication
|
||||||
//
|
//
|
||||||
|
|
|
@ -272,6 +272,15 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk)
|
||||||
return BLE_ERROR_NONE;
|
return BLE_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ble_error_t CordioSecurityManager::set_peer_csrk(
|
||||||
|
connection_handle_t connection,
|
||||||
|
const csrk_t &csrk,
|
||||||
|
bool authenticated
|
||||||
|
) {
|
||||||
|
/* TODO implement */
|
||||||
|
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Global parameters
|
// Global parameters
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue