introduce SecurityManager

This commit is contained in:
Rohit Grover 2015-06-19 08:14:12 +01:00
parent db2de9114e
commit ebd6bbceb5
5 changed files with 372 additions and 274 deletions

View file

@ -38,10 +38,8 @@ public:
virtual GattServer& getGattServer() = 0;
virtual const GattServer& getGattServer() const = 0;
virtual GattClient& getGattClient() = 0;
virtual ble_error_t initializeSecurity(bool enableBonding = true,
bool requireMITM = true,
Gap::SecurityIOCapabilities_t iocaps = Gap::IO_CAPS_NONE,
const Gap::Passkey_t passkey = NULL) = 0;
virtual SecurityManager& getSecurityManager() = 0;
virtual const SecurityManager& getSecurityManager() const = 0;
virtual void waitForEvent(void) = 0;
};

View file

@ -96,6 +96,18 @@ public:
return transport->getGattClient();
}
/*
* Accessors to Security Manager. Please refer to SecurityManager.h. All
* SecurityManager related functionality requires going through this
* accessor.
*/
const SecurityManager& securityManager() const {
return transport->getSecurityManager();
}
SecurityManager& securityManager() {
return transport->getSecurityManager();
}
/**
* Yield control to the BLE stack or to other tasks waiting for events. This
* is a sleep function which will return when there is an application
@ -107,88 +119,6 @@ public:
transport->waitForEvent();
}
/**
* Enable the BLE stack's Security Manager. The Security Manager implements
* the actual cryptographic algorithms and protocol exchanges that allow two
* devices to securely exchange data and privately detect each other.
* Calling this API is a prerequisite for encryption and pairing (bonding).
*
* @param[in] enableBonding Allow for bonding.
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
* @param[in] iocaps To specify IO capabilities of this peripheral,
* such as availability of a display or keyboard to
* support out-of-band exchanges of security data.
* @param[in] passkey To specify a static passkey.
*
* @return BLE_ERROR_NONE on success.
*/
ble_error_t initializeSecurity(bool enableBonding = true,
bool requireMITM = true,
Gap::SecurityIOCapabilities_t iocaps = Gap::IO_CAPS_NONE,
const Gap::Passkey_t passkey = NULL);
/**
* Setup a callback for when the security setup procedure (key generation
* and exchange) for a link has started. This will be skipped for bonded
* devices. The callback is passed in parameters received from the peer's
* security request: bool allowBonding, bool requireMITM, and
* SecurityIOCapabilities_t.
*/
void onSecuritySetupInitiated(Gap::SecuritySetupInitiatedCallback_t callback);
/**
* Setup a callback for when the security setup procedure (key generation
* and exchange) for a link has completed. This will be skipped for bonded
* devices. The callback is passed in the success/failure status of the
* security setup procedure.
*/
void onSecuritySetupCompleted(Gap::SecuritySetupCompletedCallback_t callback);
/**
* Setup a callback for when a link with the peer is secured. For bonded
* devices, subsequent reconnections with bonded peer will result only in
* this callback when the link is secured and setup procedures will not
* occur unless the bonding information is either lost or deleted on either
* or both sides. The callback is passed in a Gap::SecurityMode_t according
* to the level of security in effect for the secured link.
*/
void onLinkSecured(Gap::LinkSecuredCallback_t callback);
/**
* Setup a callback for successful bonding; i.e. that link-specific security
* context is stored persistently for a peer device.
*/
void onSecurityContextStored(Gap::HandleSpecificEvent_t callback);
/**
* Setup a callback for when the passkey needs to be displayed on a
* peripheral with DISPLAY capability. This happens when security is
* configured to prevent Man-In-The-Middle attacks, and a PIN (or passkey)
* needs to be exchanged between the peers to authenticate the connection
* attempt.
*/
void onPasskeyDisplay(Gap::PasskeyDisplayCallback_t callback);
/**
* Get the security status of a connection.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[out] securityStatusP security status.
*
* @return BLE_SUCCESS Or appropriate error code indicating reason for failure.
*/
ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, Gap::LinkSecurityStatus_t *securityStatusP);
/**
* Delete all peer device context and all related bonding information from
* the database within the security manager.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
*/
ble_error_t purgeAllBondingState(void);
/*
* Deprecation alert!
* All of the following are deprecated and may be dropped in a future
@ -1053,6 +983,67 @@ public:
return gattServer().write(connectionHandle, attributeHandle, value, size, localOnly);
}
/**
* Enable the BLE stack's Security Manager. The Security Manager implements
* the actual cryptographic algorithms and protocol exchanges that allow two
* devices to securely exchange data and privately detect each other.
* Calling this API is a prerequisite for encryption and pairing (bonding).
*
* @param[in] enableBonding Allow for bonding.
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
* @param[in] iocaps To specify IO capabilities of this peripheral,
* such as availability of a display or keyboard to
* support out-of-band exchanges of security data.
* @param[in] passkey To specify a static passkey.
*
* @return BLE_ERROR_NONE on success.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.initializeSecurity(...) should be replaced with
* ble.securityManager().init(...).
*/
ble_error_t initializeSecurity(bool enableBonding = true,
bool requireMITM = true,
SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE,
const SecurityManager::Passkey_t passkey = NULL) {
return securityManager().init(enableBonding, requireMITM, iocaps, passkey);
}
/**
* Get the security status of a connection.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[out] securityStatusP security status.
*
* @return BLE_SUCCESS Or appropriate error code indicating reason for failure.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.getLinkSecurity(...) should be replaced with
* ble.securityManager().getLinkSecurity(...).
*/
ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP) {
return securityManager().getLinkSecurity(connectionHandle, securityStatusP);
}
/**
* Delete all peer device context and all related bonding information from
* the database within the security manager.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.purgeAllBondingState() should be replaced with
* ble.securityManager().purgeAllBondingState().
*/
ble_error_t purgeAllBondingState(void) {
return securityManager().purgeAllBondingState();
}
/**
* Setup a callback for timeout events. Refer to Gap::TimeoutSource_t for
* possible event types.
@ -1184,6 +1175,83 @@ public:
void onUpdatesDisabled(GattServer::EventCallback_t callback);
void onConfirmationReceived(GattServer::EventCallback_t callback);
/**
* Setup a callback for when the security setup procedure (key generation
* and exchange) for a link has started. This will be skipped for bonded
* devices. The callback is passed in parameters received from the peer's
* security request: bool allowBonding, bool requireMITM, and
* SecurityIOCapabilities_t.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.onSecuritySetupInitiated(callback) should be replaced with
* ble.securityManager().onSecuritySetupInitiated(callback).
*/
void onSecuritySetupInitiated(SecurityManager::SecuritySetupInitiatedCallback_t callback) {
securityManager().onSecuritySetupInitiated(callback);
}
/**
* Setup a callback for when the security setup procedure (key generation
* and exchange) for a link has completed. This will be skipped for bonded
* devices. The callback is passed in the success/failure status of the
* security setup procedure.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.onSecuritySetupCompleted(callback) should be replaced with
* ble.securityManager().onSecuritySetupCompleted(callback).
*/
void onSecuritySetupCompleted(SecurityManager::SecuritySetupCompletedCallback_t callback) {
securityManager().onSecuritySetupCompleted(callback);
}
/**
* Setup a callback for when a link with the peer is secured. For bonded
* devices, subsequent reconnections with bonded peer will result only in
* this callback when the link is secured and setup procedures will not
* occur unless the bonding information is either lost or deleted on either
* or both sides. The callback is passed in a SecurityManager::SecurityMode_t according
* to the level of security in effect for the secured link.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.onLinkSecured(callback) should be replaced with
* ble.securityManager().onLinkSecured(callback).
*/
void onLinkSecured(SecurityManager::LinkSecuredCallback_t callback) {
securityManager().onLinkSecured(callback);
}
/**
* Setup a callback for successful bonding; i.e. that link-specific security
* context is stored persistently for a peer device.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.onSecurityContextStored(callback) should be replaced with
* ble.securityManager().onSecurityContextStored(callback).
*/
void onSecurityContextStored(SecurityManager::HandleSpecificEvent_t callback) {
securityManager().onSecurityContextStored(callback);
}
/**
* Setup a callback for when the passkey needs to be displayed on a
* peripheral with DISPLAY capability. This happens when security is
* configured to prevent Man-In-The-Middle attacks, and a PIN (or passkey)
* needs to be exchanged between the peers to authenticate the connection
* attempt.
*
* @note: This API is now *deprecated* and will be dropped in the future.
* You should use the parallel API from SecurityManager directly. A former
* call to ble.onPasskeyDisplay(callback) should be replaced with
* ble.securityManager().onPasskeyDisplay(callback).
*/
void onPasskeyDisplay(SecurityManager::PasskeyDisplayCallback_t callback) {
return securityManager().onPasskeyDisplay(callback);
}
public:
BLE() : transport(createBLEInstance()) {
/* empty */
@ -1247,55 +1315,4 @@ BLE::onConfirmationReceived(GattServer::EventCallback_t callback)
transport->getGattServer().setOnConfirmationReceived(callback);
}
inline ble_error_t
BLE::initializeSecurity(bool enableBonding,
bool requireMITM,
Gap::SecurityIOCapabilities_t iocaps,
const Gap::Passkey_t passkey)
{
return transport->initializeSecurity(enableBonding, requireMITM, iocaps, passkey);
}
inline void
BLE::onSecuritySetupInitiated(Gap::SecuritySetupInitiatedCallback_t callback)
{
gap().setOnSecuritySetupInitiated(callback);
}
inline void
BLE::onSecuritySetupCompleted(Gap::SecuritySetupCompletedCallback_t callback)
{
gap().setOnSecuritySetupCompleted(callback);
}
inline void
BLE::onLinkSecured(Gap::LinkSecuredCallback_t callback)
{
gap().setOnLinkSecured(callback);
}
inline void
BLE::onSecurityContextStored(Gap::HandleSpecificEvent_t callback)
{
gap().setOnSecurityContextStored(callback);
}
inline void
BLE::onPasskeyDisplay(Gap::PasskeyDisplayCallback_t callback)
{
return gap().setOnPasskeyDisplay(callback);
}
inline ble_error_t
BLE::getLinkSecurity(Gap::Handle_t connectionHandle, Gap::LinkSecurityStatus_t *securityStatusP)
{
return gap().getLinkSecurity(connectionHandle, securityStatusP);
}
inline ble_error_t
BLE::purgeAllBondingState(void)
{
return gap().purgeAllBondingState();
}
#endif // ifndef __BLE_H__

View file

@ -126,58 +126,6 @@ public:
}
};
enum SecurityMode_t {
SECURITY_MODE_NO_ACCESS,
SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< require no protection, open link. */
SECURITY_MODE_ENCRYPTION_NO_MITM, /**< require encryption, but no MITM protection. */
SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< require encryption and MITM protection. */
SECURITY_MODE_SIGNED_NO_MITM, /**< require signing or encryption, but no MITM protection. */
SECURITY_MODE_SIGNED_WITH_MITM, /**< require signing or encryption, and MITM protection. */
};
/**
* @brief Defines possible security status/states.
*
* @details Defines possible security status/states of a link when requested by getLinkSecurity().
*/
enum LinkSecurityStatus_t {
NOT_ENCRYPTED, /**< The link is not secured. */
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
ENCRYPTED /**< The link is secure.*/
};
enum SecurityIOCapabilities_t {
IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display Only. */
IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and Yes/No entry. */
IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard Only. */
IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */
IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and Display. */
};
enum SecurityCompletionStatus_t {
SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */
SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */
SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */
SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user canceled or other). */
SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */
SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */
SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */
SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */
SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */
SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */
SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */
SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */
SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */
};
/**
* Declaration of type containing a passkey to be used during pairing. This
* is passed into initializeSecurity() to specify a pre-programmed passkey
* for authentication instead of generating a random one.
*/
static const unsigned PASSKEY_LEN = 6;
typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
static const uint16_t UNIT_1_25_MS = 1250; /**< Number of microseconds in 1.25 milliseconds. */
static const uint16_t UNIT_0_625_MS = 625; /**< Number of microseconds in 0.625 milliseconds. */
static uint16_t MSEC_TO_GAP_DURATION_UNITS(uint32_t durationInMillis) {
@ -192,13 +140,8 @@ public:
typedef void (*TimeoutEventCallback_t)(TimeoutSource_t source);
typedef void (*ConnectionEventCallback_t)(const ConnectionCallbackParams_t *params);
typedef void (*HandleSpecificEvent_t)(Handle_t handle);
typedef void (*DisconnectionEventCallback_t)(Handle_t, DisconnectionReason_t);
typedef void (*RadioNotificationEventCallback_t) (bool radio_active); /* gets passed true for ACTIVE; false for INACTIVE. */
typedef void (*SecuritySetupInitiatedCallback_t)(Handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps);
typedef void (*SecuritySetupCompletedCallback_t)(Handle_t, SecurityCompletionStatus_t status);
typedef void (*LinkSecuredCallback_t)(Handle_t handle, SecurityMode_t securityMode);
typedef void (*PasskeyDisplayCallback_t)(Handle_t handle, const Passkey_t passkey);
/*
* These functions must be defined in the platform-specific sub-class.
@ -309,9 +252,6 @@ public:
*/
virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params) = 0;
virtual ble_error_t purgeAllBondingState(void) = 0;
virtual ble_error_t getLinkSecurity(Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) = 0;
/**
* Set the device name characteristic in the GAP service.
* @param[in] deviceName
@ -802,35 +742,6 @@ public:
*/
virtual void onRadioNotification(RadioNotificationEventCallback_t callback) {radioNotificationCallback = callback;}
/**
* To indicate that security procedure for link has started.
*/
virtual void setOnSecuritySetupInitiated(SecuritySetupInitiatedCallback_t callback) {onSecuritySetupInitiated = callback;}
/**
* To indicate that security procedure for link has completed.
*/
virtual void setOnSecuritySetupCompleted(SecuritySetupCompletedCallback_t callback) {onSecuritySetupCompleted = callback;}
/**
* To indicate that link with the peer is secured. For bonded devices,
* subsequent re-connections with bonded peer will result only in this callback
* when the link is secured and setup procedures will not occur unless the
* bonding information is either lost or deleted on either or both sides.
*/
virtual void setOnLinkSecured(LinkSecuredCallback_t callback) {onLinkSecured = callback;}
/**
* To indicate that device context is stored persistently.
*/
virtual void setOnSecurityContextStored(HandleSpecificEvent_t callback) {onSecurityContextStored = callback;}
/**
* To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability.
*/
virtual void setOnPasskeyDisplay(PasskeyDisplayCallback_t callback) {onPasskeyDisplay = callback;}
protected:
Gap() :
_advParams(),
@ -842,11 +753,6 @@ protected:
connectionCallback(NULL),
disconnectionCallback(NULL),
radioNotificationCallback(),
onSecuritySetupInitiated(),
onSecuritySetupCompleted(),
onLinkSecured(),
onSecurityContextStored(),
onPasskeyDisplay(),
onAdvertisementReport(),
disconnectionCallChain() {
_advPayload.clear();
@ -876,36 +782,6 @@ public:
disconnectionCallChain.call();
}
void processSecuritySetupInitiatedEvent(Handle_t handle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) {
if (onSecuritySetupInitiated) {
onSecuritySetupInitiated(handle, allowBonding, requireMITM, iocaps);
}
}
void processSecuritySetupCompletedEvent(Handle_t handle, SecurityCompletionStatus_t status) {
if (onSecuritySetupCompleted) {
onSecuritySetupCompleted(handle, status);
}
}
void processLinkSecuredEvent(Handle_t handle, SecurityMode_t securityMode) {
if (onLinkSecured) {
onLinkSecured(handle, securityMode);
}
}
void processSecurityContextStoredEvent(Handle_t handle) {
if (onSecurityContextStored) {
onSecurityContextStored(handle);
}
}
void processPasskeyDisplayEvent(Handle_t handle, const Passkey_t passkey) {
if (onPasskeyDisplay) {
onPasskeyDisplay(handle, passkey);
}
}
void processAdvertisementReport(const Address_t peerAddr,
int8_t rssi,
bool isScanResponse,
@ -941,11 +817,6 @@ protected:
ConnectionEventCallback_t connectionCallback;
DisconnectionEventCallback_t disconnectionCallback;
RadioNotificationEventCallback_t radioNotificationCallback;
SecuritySetupInitiatedCallback_t onSecuritySetupInitiated;
SecuritySetupCompletedCallback_t onSecuritySetupCompleted;
LinkSecuredCallback_t onLinkSecured;
HandleSpecificEvent_t onSecurityContextStored;
PasskeyDisplayCallback_t onPasskeyDisplay;
AdvertisementReportCallback_t onAdvertisementReport;
CallChain disconnectionCallChain;

View file

@ -18,6 +18,7 @@
#define __GATT_CHARACTERISTIC_H__
#include "Gap.h"
#include "SecurityManager.h"
#include "GattAttribute.h"
#include "GattCallbackParamTypes.h"
#include "FunctionPointerWithContext.h"
@ -331,7 +332,7 @@ public:
unsigned numDescriptors = 0) :
_valueAttribute(uuid, valuePtr, initialLen, maxLen),
_properties(props),
_requiredSecurity(Gap::SECURITY_MODE_ENCRYPTION_OPEN_LINK),
_requiredSecurity(SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK),
_descriptors(descriptors),
_descriptorCount(numDescriptors),
enabledReadAuthorization(false),
@ -347,7 +348,7 @@ public:
*
* @param securityMode Can be one of encryption or signing, with or without protection for MITM (man in the middle attacks).
*/
void requireSecurity(Gap::SecurityMode_t securityMode) {
void requireSecurity(SecurityManager::SecurityMode_t securityMode) {
_requiredSecurity = securityMode;
}
@ -422,7 +423,7 @@ public:
const GattAttribute& getValueAttribute() const {return _valueAttribute; }
GattAttribute::Handle_t getValueHandle(void) const {return getValueAttribute().getHandle();}
uint8_t getProperties(void) const {return _properties; }
Gap::SecurityMode_t getRequiredSecurity() const {return _requiredSecurity; }
SecurityManager::SecurityMode_t getRequiredSecurity() const {return _requiredSecurity; }
uint8_t getDescriptorCount(void) const {return _descriptorCount; }
bool isReadAuthorizationEnabled() const {return enabledReadAuthorization; }
bool isWriteAuthorizationEnabled() const {return enabledWriteAuthorization; }
@ -436,11 +437,11 @@ public:
}
private:
GattAttribute _valueAttribute;
uint8_t _properties;
Gap::SecurityMode_t _requiredSecurity;
GattAttribute **_descriptors;
uint8_t _descriptorCount;
GattAttribute _valueAttribute;
uint8_t _properties;
SecurityManager::SecurityMode_t _requiredSecurity;
GattAttribute **_descriptors;
uint8_t _descriptorCount;
bool enabledReadAuthorization;
bool enabledWriteAuthorization;

211
public/SecurityManager.h Normal file
View file

@ -0,0 +1,211 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2015 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 __SECURITY_MANAGER_H__
#define __SECURITY_MANAGER_H__
#include <stdint.h>
#include "Gap.h"
class SecurityManager {
public:
enum SecurityMode_t {
SECURITY_MODE_NO_ACCESS,
SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< require no protection, open link. */
SECURITY_MODE_ENCRYPTION_NO_MITM, /**< require encryption, but no MITM protection. */
SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< require encryption and MITM protection. */
SECURITY_MODE_SIGNED_NO_MITM, /**< require signing or encryption, but no MITM protection. */
SECURITY_MODE_SIGNED_WITH_MITM, /**< require signing or encryption, and MITM protection. */
};
/**
* @brief Defines possible security status/states.
*
* @details Defines possible security status/states of a link when requested by getLinkSecurity().
*/
enum LinkSecurityStatus_t {
NOT_ENCRYPTED, /**< The link is not secured. */
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
ENCRYPTED /**< The link is secure.*/
};
enum SecurityIOCapabilities_t {
IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display Only. */
IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and Yes/No entry. */
IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard Only. */
IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */
IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and Display. */
};
enum SecurityCompletionStatus_t {
SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */
SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */
SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */
SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user canceled or other). */
SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */
SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */
SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */
SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */
SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */
SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */
SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */
SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */
SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */
};
/**
* Declaration of type containing a passkey to be used during pairing. This
* is passed into initializeSecurity() to specify a pre-programmed passkey
* for authentication instead of generating a random one.
*/
static const unsigned PASSKEY_LEN = 6;
typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */
public:
typedef void (*HandleSpecificEvent_t)(Gap::Handle_t handle);
typedef void (*SecuritySetupInitiatedCallback_t)(Gap::Handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps);
typedef void (*SecuritySetupCompletedCallback_t)(Gap::Handle_t, SecurityCompletionStatus_t status);
typedef void (*LinkSecuredCallback_t)(Gap::Handle_t handle, SecurityMode_t securityMode);
typedef void (*PasskeyDisplayCallback_t)(Gap::Handle_t handle, const Passkey_t passkey);
public:
/**
* Enable the BLE stack's Security Manager. The Security Manager implements
* the actual cryptographic algorithms and protocol exchanges that allow two
* devices to securely exchange data and privately detect each other.
* Calling this API is a prerequisite for encryption and pairing (bonding).
*
* @param[in] enableBonding Allow for bonding.
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
* @param[in] iocaps To specify IO capabilities of this peripheral,
* such as availability of a display or keyboard to
* support out-of-band exchanges of security data.
* @param[in] passkey To specify a static passkey.
*
* @return BLE_ERROR_NONE on success.
*/
virtual ble_error_t init(bool enableBonding = true,
bool requireMITM = true,
SecurityIOCapabilities_t iocaps = IO_CAPS_NONE,
const Passkey_t passkey = NULL) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
/**
* Get the security status of a connection.
*
* @param[in] connectionHandle Handle to identify the connection.
* @param[out] securityStatusP security status.
*
* @return BLE_SUCCESS Or appropriate error code indicating reason for failure.
*/
virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
/**
* Delete all peer device context and all related bonding information from
* the database within the security manager.
*
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
*/
virtual ble_error_t purgeAllBondingState(void) {
return BLE_ERROR_NOT_IMPLEMENTED; /* default implementation; override this if security is supported. */
}
public:
/**
* To indicate that security procedure for link has started.
*/
virtual void onSecuritySetupInitiated(SecuritySetupInitiatedCallback_t callback) {securitySetupInitiatedCallback = callback;}
/**
* To indicate that security procedure for link has completed.
*/
virtual void onSecuritySetupCompleted(SecuritySetupCompletedCallback_t callback) {securitySetupCompletedCallback = callback;}
/**
* To indicate that link with the peer is secured. For bonded devices,
* subsequent re-connections with bonded peer will result only in this callback
* when the link is secured and setup procedures will not occur unless the
* bonding information is either lost or deleted on either or both sides.
*/
virtual void onLinkSecured(LinkSecuredCallback_t callback) {linkSecuredCallback = callback;}
/**
* To indicate that device context is stored persistently.
*/
virtual void onSecurityContextStored(HandleSpecificEvent_t callback) {securityContextStoredCallback = callback;}
/**
* To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability.
*/
virtual void onPasskeyDisplay(PasskeyDisplayCallback_t callback) {passkeyDisplayCallback = callback;}
public:
void processSecuritySetupInitiatedEvent(Gap::Handle_t handle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) {
if (securitySetupInitiatedCallback) {
securitySetupInitiatedCallback(handle, allowBonding, requireMITM, iocaps);
}
}
void processSecuritySetupCompletedEvent(Gap::Handle_t handle, SecurityCompletionStatus_t status) {
if (securitySetupCompletedCallback) {
securitySetupCompletedCallback(handle, status);
}
}
void processLinkSecuredEvent(Gap::Handle_t handle, SecurityMode_t securityMode) {
if (linkSecuredCallback) {
linkSecuredCallback(handle, securityMode);
}
}
void processSecurityContextStoredEvent(Gap::Handle_t handle) {
if (securityContextStoredCallback) {
securityContextStoredCallback(handle);
}
}
void processPasskeyDisplayEvent(Gap::Handle_t handle, const Passkey_t passkey) {
if (passkeyDisplayCallback) {
passkeyDisplayCallback(handle, passkey);
}
}
protected:
SecurityManager() :
securitySetupInitiatedCallback(),
securitySetupCompletedCallback(),
linkSecuredCallback(),
securityContextStoredCallback(),
passkeyDisplayCallback() {
/* empty */
}
protected:
SecuritySetupInitiatedCallback_t securitySetupInitiatedCallback;
SecuritySetupCompletedCallback_t securitySetupCompletedCallback;
LinkSecuredCallback_t linkSecuredCallback;
HandleSpecificEvent_t securityContextStoredCallback;
PasskeyDisplayCallback_t passkeyDisplayCallback;
};
#endif /*__SECURITY_MANAGER_H__*/