mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'security-manager-dev' of https://github.com/paul-szczepanek-arm/mbed-os into sc-nordic
commit
f53a0e4906
|
@ -262,6 +262,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 {
|
||||
/**
|
||||
|
|
|
@ -116,6 +116,15 @@ public:
|
|||
* The server does not acknowledge the status of the operation.
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -313,13 +322,24 @@ private:
|
|||
* Returns the CSRK for the connection. Called by the security db.
|
||||
*
|
||||
* @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(
|
||||
pal::SecurityDb::entry_handle_t connection,
|
||||
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.
|
||||
*
|
||||
|
@ -434,6 +454,8 @@ private:
|
|||
uint8_t oob_mitm_protection:1;
|
||||
uint8_t oob_present:1;
|
||||
uint8_t legacy_pairing_oob_request_pending:1;
|
||||
|
||||
uint8_t csrk_failures:2;
|
||||
};
|
||||
|
||||
pal::SecurityManager &_pal;
|
||||
|
@ -441,6 +463,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;
|
||||
|
@ -503,6 +526,12 @@ public:
|
|||
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
|
||||
*/
|
||||
virtual void on_slave_security_request(
|
||||
|
@ -572,7 +601,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
|
||||
);
|
||||
|
|
|
@ -280,6 +280,16 @@ public:
|
|||
connection_handle_t connection
|
||||
) = 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.
|
||||
* This might result in the stack enabling encryption, or pairing/re-pairing.
|
||||
|
@ -399,7 +409,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 +554,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 +583,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 +594,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 +608,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 +619,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 +636,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 +655,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 +671,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 +686,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 +696,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 +712,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 +725,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 +743,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 +758,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 +779,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 +796,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 +810,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 +836,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 +849,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 +859,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,12 +869,25 @@ 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
|
||||
) = 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
|
||||
//
|
||||
|
@ -875,7 +897,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 +925,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 +934,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 +949,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 +963,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 +976,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 +989,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 +998,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:
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <ble/DiscoveredCharacteristic.h>
|
||||
#include "ble/generic/GenericGattClient.h"
|
||||
#include "ble/blecommon.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
#include "ble/generic/GenericSecurityManager.h"
|
||||
#include <algorithm>
|
||||
|
||||
using ble::pal::AttServerMessage;
|
||||
|
@ -38,6 +40,11 @@ using ble::pal::AttHandleValueIndication;
|
|||
using ble::pal::AttHandleValueNotification;
|
||||
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 generic {
|
||||
|
||||
|
@ -1074,67 +1081,77 @@ ble_error_t GenericGattClient::write(
|
|||
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 (length > (uint16_t)(mtu - 3)) {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
return _pal_client->write_without_response(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, length)
|
||||
);
|
||||
} else {
|
||||
uint8_t* data = NULL;
|
||||
if (cmd == GattClient::GATT_OP_WRITE_CMD) {
|
||||
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
}
|
||||
return _pal_client->write_without_response(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, length)
|
||||
);
|
||||
} else if (cmd == GattClient::GATT_OP_SIGNED_WRITE_CMD) {
|
||||
/*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)) {
|
||||
data = (uint8_t*) malloc(length);
|
||||
if (data == NULL) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
memcpy(data, value, length);
|
||||
}
|
||||
if (length > (uint16_t) (mtu - WRITE_HEADER_LENGTH)) {
|
||||
data = (uint8_t*) malloc(length);
|
||||
if (data == NULL) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
memcpy(data, value, length);
|
||||
}
|
||||
|
||||
WriteControlBlock* write_pcb = new(std::nothrow) WriteControlBlock(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
data,
|
||||
length
|
||||
);
|
||||
WriteControlBlock* write_pcb = new (std::nothrow) WriteControlBlock(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
data,
|
||||
length
|
||||
);
|
||||
|
||||
if (write_pcb == NULL) {
|
||||
free(data);
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
if (write_pcb == NULL) {
|
||||
free(data);
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
insert_control_block(write_pcb);
|
||||
insert_control_block(write_pcb);
|
||||
|
||||
ble_error_t err = BLE_ERROR_UNSPECIFIED;
|
||||
if (data) {
|
||||
err = _pal_client->queue_prepare_write(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, mtu - 5),
|
||||
/* offset */ 0
|
||||
);
|
||||
} else {
|
||||
err = _pal_client->write_attribute(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, length)
|
||||
);
|
||||
}
|
||||
ble_error_t err = BLE_ERROR_UNSPECIFIED;
|
||||
if (data) {
|
||||
err = _pal_client->queue_prepare_write(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, mtu - PREPARE_WRITE_HEADER_LENGTH),
|
||||
/* offset */0
|
||||
);
|
||||
} else {
|
||||
err = _pal_client->write_attribute(
|
||||
connection_handle,
|
||||
attribute_handle,
|
||||
make_const_ArrayView(value, length)
|
||||
);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
remove_control_block(write_pcb);
|
||||
delete write_pcb;
|
||||
}
|
||||
if (err) {
|
||||
remove_control_block(write_pcb);
|
||||
delete write_pcb;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void GenericGattClient::onServiceDiscoveryTermination(
|
||||
|
|
|
@ -140,14 +140,10 @@ ble_error_t GenericSecurityManager::requestPairing(connection_handle_t connectio
|
|||
* use when roles are changed */
|
||||
if (_master_sends_keys) {
|
||||
initiator_distribution = _default_key_distribution;
|
||||
}
|
||||
|
||||
/* override default if 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());
|
||||
/* override default if requested */
|
||||
if (cb->signing_override_default) {
|
||||
initiator_distribution.set_signing(cb->signing_requested);
|
||||
}
|
||||
}
|
||||
|
||||
KeyDistribution responder_distribution(_default_key_distribution);
|
||||
|
@ -312,19 +308,27 @@ ble_error_t GenericSecurityManager::enableSigning(
|
|||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
cb->signing_requested = enabled;
|
||||
cb->signing_override_default = false;
|
||||
cb->signing_override_default = true;
|
||||
|
||||
if (cb->encrypted) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
if (!cb->csrk_stored && cb->signing_requested) {
|
||||
init_signing();
|
||||
if (cb->is_master) {
|
||||
return requestPairing(connection);
|
||||
if (enabled && !cb->signing_requested && !_default_key_distribution.get_signing()) {
|
||||
cb->signing_requested = true;
|
||||
if (cb->csrk_stored) {
|
||||
/* used the stored ones when available */
|
||||
_db.get_entry_peer_csrk(
|
||||
mbed::callback(this, &GenericSecurityManager::set_peer_csrk_cb),
|
||||
cb->db_entry
|
||||
);
|
||||
} 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;
|
||||
|
@ -506,6 +510,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 +560,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.data(), 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(
|
||||
|
@ -698,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(
|
||||
pal::SecurityDb::entry_handle_t db_entry,
|
||||
const csrk_t *csrk
|
||||
|
@ -720,13 +771,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,6 +828,17 @@ void GenericSecurityManager::on_connected(
|
|||
if (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(
|
||||
|
@ -876,6 +943,31 @@ void GenericSecurityManager::on_valid_mic_timeout(connection_handle_t 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(
|
||||
connection_handle_t connection,
|
||||
AuthenticationMask authentication
|
||||
|
@ -996,6 +1088,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 +1107,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 +1121,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;
|
||||
}
|
||||
|
||||
|
@ -1190,7 +1284,8 @@ GenericSecurityManager::ControlBlock_t::ControlBlock_t() :
|
|||
attempt_oob(false),
|
||||
oob_mitm_protection(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)
|
||||
{
|
||||
|
|
|
@ -239,6 +239,15 @@ public:
|
|||
*/
|
||||
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
|
||||
//
|
||||
|
@ -300,9 +309,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();
|
||||
|
|
|
@ -272,6 +272,15 @@ ble_error_t CordioSecurityManager::set_csrk(const csrk_t& csrk)
|
|||
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
|
||||
//
|
||||
|
@ -407,17 +416,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 +645,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
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue