Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SecurityManager.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef SECURITY_MANAGER_H_ 00018 #define SECURITY_MANAGER_H_ 00019 00020 #include <stdint.h> 00021 00022 #include "Gap.h" 00023 #include "CallChainOfFunctionPointersWithContext.h" 00024 #include "ble/BLETypes.h" 00025 00026 /** 00027 * Overview 00028 * 00029 * Security Manager is used to provide link security through encryption, signing and authentication 00030 * which are made possible by pairing and optionally bonding. Pairing is the process of establishing 00031 * and/or exchanging keys used for the current connection. Bonding means saving this information so that 00032 * it can later be used after reconnecting without having to pair again. This saves time and power. 00033 * 00034 * There are many ways to provide these at different levels of security depending on your requirements 00035 * and the facilities provided by the application. The process starts with initialising the SecurityManager 00036 * with default options for new connections. Some settings can later be changed per link or globally. 00037 * 00038 * The important settings in the init() function are the MITM requirement and IO capabilities. Man in the 00039 * Middle (MITM) protection prevents an attack where one device can impersonate another device by 00040 * pairing with both devices at the same time. This protection is achieved by sharing some information 00041 * between the devices through some independent channel. The IO capabilities of both devices dictate 00042 * what algorithm is used. For details @see BLUETOOTH SPECIFICATION Version 5.0 | Vol 3, Part H - 2.3.5.1. 00043 * You can change the IO capabilities after initialisation with setIoCapability(). This will take effect 00044 * for all subsequent pairings. 00045 * 00046 * Sharing this information through IO capabilities means user interaction which limits the degree of 00047 * protection due to the limit of the amount of data that we can expect the user to transfer. Another 00048 * solution is using OOB (out of band) communication to transfer this data instead which can send much 00049 * more data making MITM attack even less likely to succeed. OOB data has to be exchanged by the application 00050 * and provided to the Security Manager. Use setOOBDataUsage() to indicate you want to use it. The same call also 00051 * allows you to set whether or not the communication channel you are using to transmit the OOB data is 00052 * itself secure against MITM protection - this will set the level of the link security achieved using pairing 00053 * that uses this data. 00054 * 00055 * The most secure pairing is provided by Secure Connections which relies on Elliptical Curve Cryptography. 00056 * Support for Secure Connections is dependent on both the stack and controller on both sides supporting 00057 * it. If either side doesn't support it Legacy Pairing will be used. This is an older standard of pairing. 00058 * If higher security is required legacy pairing can be disabled by calling allowLegacyPairing(false); 00059 * 00060 * \par How to use 00061 * 00062 * First thing you need to do is to initialise the manager by calling init() with your chosen settings. 00063 * 00064 * The SecurityManager communicates with your application through events. These will trigger calls in 00065 * the EventHandler which you must provide by calling the setSecurityManagerEventHandler() function. 00066 * 00067 * The most important process is pairing. This may be triggered manually by calling requestPairing() or 00068 * may be called as a result of the application requiring encryption by calling setLinkEncryption() or 00069 * as a result of the application requiring MITM protection through requestAuthentication(). 00070 * 00071 * All these can be implicitly called by using setLinkSecurity() to conveniently set the required 00072 * security for the link. The SecurityManager will trigger all the process required to achieve the set 00073 * security level. Security level can only be escalated. Asking the Security Manager for a lower 00074 * security level than the existing one will not fail but will result in a event informing the 00075 * application through linkEncryptionResult() of the current level (which remains unchanged). 00076 * 00077 * Depending on the IO capabilities and OOB usage settings different pairing algorithms will be chosen. 00078 * They will produce appropriate events which must be handled by your EventHandler. If your event handler 00079 * doesn't support all the calls you must not set IO capabilities or set OOB usage in such a way that would 00080 * trigger them or else the pairing will fail (usually by timing out). 00081 * 00082 * The simplest example is a pairing of a device with no IO capabilities and no OOB data available. 00083 * With such limited pairing capabilities the "just works" method will be employed. This does not provide 00084 * any MITM protection. The pairing (triggered implicitly or called explicitly) will result in an event 00085 * being generated on the peer calling pairingRequest(). The event handler must make a decision (either in 00086 * the application itself or based on user interaction) whether to accept the pairing and call 00087 * accetPairing() or cancelPairing(). The result will be communicated on both peers through an event calling 00088 * pairingResult() in the EventHandler. 00089 * 00090 * \par Sequence diagrams 00091 * 00092 * Sequence diagram "Just Works" pairing 00093 * 00094 * \verbatim 00095 * /----------- Device 1 --------------\ *------ BLE link ------* /-------------- Device 2 -------------\ 00096 * 00097 * App EventHandler SecurityManager SecurityManager EventHandler App 00098 * | | | | | | 00099 * |---------------------------> requestPairing() | | | 00100 * | | |------[pairing start]------>| | | 00101 * | | | |----------------> pairingRequest() ->| 00102 * | | | acceptPairing() <------------------------ | 00103 * | | |<---[pairing complete]----->| | | 00104 * |<- pairingResult() <---------------| |----------------> pairingResult() -->| 00105 * | | | | | | 00106 * \endverbatim 00107 * 00108 * @note the requestPairing() call isn't required to trigger pairing. Pairing will also be triggered 00109 * if you request encryption and authentication and no bonding information is available. The sequence will 00110 * be the same save for the lack of explicit requestPairing() call. 00111 * 00112 * 00113 * Sequence diagram Encryption request when bonding information is available 00114 * 00115 * \verbatim 00116 * /----------- Device 1 --------------\ *------ BLE link ------* /-------------- Device 2 -------------\ 00117 * 00118 * App EventHandler SecurityManager SecurityManager EventHandler App 00119 * | | | | | | 00120 * |---------------------------> setLinkEncryption() | | | 00121 * | | |<-[encryption established]->| | | 00122 * |<- linkEncryptionResult() <--------| |---------> linkEncryptionResult() -->| 00123 * | | | | | | 00124 * \endverbatim 00125 * 00126 * @note if bonding information is not available, pairing will be triggered 00127 * 00128 * 00129 * Sequence diagram for Secure Connections passkey entry pairing with one device having a display only 00130 * and other a keyboard 00131 * 00132 * \verbatim 00133 * /----------- Device 1 (keyboard) ---\ *------ BLE link ------* /-------------- Device 2 (display) ---\ 00134 * 00135 * App EventHandler SecurityManager SecurityManager EventHandler App 00136 * | | | | | | 00137 * |---------------------------> requestPairing() | | | 00138 * | | |------[pairing start]------>| | | 00139 * | | | |----------------> pairingRequest() ->| 00140 * | | | acceptPairing() <------------------------ | 00141 * | | |<---[secure con. pairing]-->| | | 00142 * |<- passkeyRequest() <--------------| |----------------> passkeyDisplay() ->| 00143 * | | | | | | 00144 * 00145 * user reads the passkey on Device 2 and inputs it on Device 1 00146 * 00147 * | | | | | | 00148 * |-------------------------->passkeyEntered() | | | 00149 * | | |<---[pairing complete]----->| | | 00150 * |<- pairingResult() <---------------| |----------------> pairingResult() -->| 00151 * | | | | | | 00152 * \endverbatim 00153 * 00154 */ 00155 00156 class SecurityManager { 00157 public: 00158 /** events sent and received when passkey is being entered */ 00159 enum Keypress_t { 00160 KEYPRESS_STARTED, /**< Passkey entry started */ 00161 KEYPRESS_ENTERED, /**< Passkey digit entered */ 00162 KEYPRESS_ERASED, /**< Passkey digit erased */ 00163 KEYPRESS_CLEARED, /**< Passkey cleared */ 00164 KEYPRESS_COMPLETED, /**< Passkey entry completed */ 00165 }; 00166 00167 /** level of security required from the link by the application */ 00168 enum SecurityMode_t { 00169 SECURITY_MODE_NO_ACCESS, 00170 SECURITY_MODE_ENCRYPTION_OPEN_LINK, /**< Require no protection, open link. */ 00171 SECURITY_MODE_ENCRYPTION_NO_MITM, /**< Require encryption, but no MITM protection. */ 00172 SECURITY_MODE_ENCRYPTION_WITH_MITM, /**< Require encryption and MITM protection. */ 00173 SECURITY_MODE_SIGNED_NO_MITM, /**< Require signing or encryption, but no MITM protection. */ 00174 SECURITY_MODE_SIGNED_WITH_MITM, /**< Require signing or encryption, and MITM protection. */ 00175 }; 00176 00177 /** 00178 * @brief Defines possible security status or states. 00179 * 00180 * @details Defines possible security status or states of a link when requested by getLinkSecurity(). 00181 */ 00182 enum LinkSecurityStatus_t { 00183 NOT_ENCRYPTED, /**< The link is not secured. */ 00184 ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/ 00185 ENCRYPTED /**< The link is secure.*/ 00186 }; 00187 00188 /** Input/output capability of the device and application */ 00189 enum SecurityIOCapabilities_t { 00190 IO_CAPS_DISPLAY_ONLY = 0x00, /**< Display only. */ 00191 IO_CAPS_DISPLAY_YESNO = 0x01, /**< Display and yes/no entry. */ 00192 IO_CAPS_KEYBOARD_ONLY = 0x02, /**< Keyboard only. */ 00193 IO_CAPS_NONE = 0x03, /**< No I/O capabilities. */ 00194 IO_CAPS_KEYBOARD_DISPLAY = 0x04, /**< Keyboard and display. */ 00195 }; 00196 00197 /** Result of security requests */ 00198 enum SecurityCompletionStatus_t { 00199 SEC_STATUS_SUCCESS = 0x00, /**< Procedure completed with success. */ 00200 SEC_STATUS_TIMEOUT = 0x01, /**< Procedure timed out. */ 00201 SEC_STATUS_PDU_INVALID = 0x02, /**< Invalid PDU received. */ 00202 SEC_STATUS_PASSKEY_ENTRY_FAILED = 0x81, /**< Passkey entry failed (user cancelled or other). */ 00203 SEC_STATUS_OOB_NOT_AVAILABLE = 0x82, /**< Out of Band Key not available. */ 00204 SEC_STATUS_AUTH_REQ = 0x83, /**< Authentication requirements not met. */ 00205 SEC_STATUS_CONFIRM_VALUE = 0x84, /**< Confirm value failed. */ 00206 SEC_STATUS_PAIRING_NOT_SUPP = 0x85, /**< Pairing not supported. */ 00207 SEC_STATUS_ENC_KEY_SIZE = 0x86, /**< Encryption key size. */ 00208 SEC_STATUS_SMP_CMD_UNSUPPORTED = 0x87, /**< Unsupported SMP command. */ 00209 SEC_STATUS_UNSPECIFIED = 0x88, /**< Unspecified reason. */ 00210 SEC_STATUS_REPEATED_ATTEMPTS = 0x89, /**< Too little time elapsed since last attempt. */ 00211 SEC_STATUS_INVALID_PARAMS = 0x8A, /**< Invalid parameters. */ 00212 SEC_STATUS_DHKEY_CHECK_FAILED = 0x8B, /**< DHKey received doesn’t match locally calculated one. */ 00213 SEC_STATUS_COMPARISON_FAILED = 0x8C, /**< Values in the numeric comparison protocol do not match. */ 00214 }; 00215 00216 /** 00217 * Declaration of type containing a passkey to be used during pairing. This 00218 * is passed into initializeSecurity() to specify a pre-programmed passkey 00219 * for authentication instead of generating a random one. 00220 */ 00221 static const unsigned PASSKEY_LEN = 6; 00222 typedef uint8_t Passkey_t[PASSKEY_LEN]; /**< 6-digit passkey in ASCII ('0'-'9' digits only). */ 00223 00224 typedef FunctionPointerWithContext<const SecurityManager *> SecurityManagerShutdownCallback_t ; 00225 typedef CallChainOfFunctionPointersWithContext<const SecurityManager *> SecurityManagerShutdownCallbackChain_t ; 00226 00227 /* legacy callbacks, please use SecurityManagerEventHandler instead */ 00228 typedef void (*HandleSpecificEvent_t)(ble::connection_handle_t connectionHandle); 00229 typedef void (*SecuritySetupInitiatedCallback_t)(ble::connection_handle_t, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps); 00230 typedef void (*SecuritySetupCompletedCallback_t)(ble::connection_handle_t, SecurityCompletionStatus_t status); 00231 typedef void (*LinkSecuredCallback_t)(ble::connection_handle_t connectionHandle, SecurityMode_t securityMode); 00232 typedef void (*PasskeyDisplayCallback_t)(ble::connection_handle_t connectionHandle, const Passkey_t passkey); 00233 00234 /** The stack will use these functions to signal events to the application, 00235 * subclass to override handlers. Use SecurityManager::setSecurityManagerEventHandler 00236 * to set the interface implementation to be used. */ 00237 class EventHandler { 00238 public: 00239 EventHandler() {}; 00240 virtual ~EventHandler() {}; 00241 00242 //////////////////////////////////////////////////////////////////////////// 00243 // Pairing 00244 // 00245 00246 /** 00247 * Request application to accept or reject pairing. Application should respond by 00248 * calling the appropriate function: acceptPairingRequest or cancelPairingRequest 00249 * 00250 * @param[in] connectionHandle connection connectionHandle 00251 */ 00252 virtual void pairingRequest(ble::connection_handle_t connectionHandle) { 00253 (void)connectionHandle; 00254 } 00255 00256 /** 00257 * Indicate to the application that pairing has completed. 00258 * 00259 * @param[in] connectionHandle connection connectionHandle 00260 * @param[in] result result of the pairing indicating success or reason for failure 00261 */ 00262 virtual void pairingResult(ble::connection_handle_t connectionHandle, SecurityCompletionStatus_t result) { 00263 (void)connectionHandle; 00264 (void)result; 00265 } 00266 00267 //////////////////////////////////////////////////////////////////////////// 00268 // Security 00269 // 00270 00271 /** 00272 * Deliver the requested whitelist to the application. 00273 * 00274 * @param[in] whitelist pointer to the whitelist filled with entries based on bonding information 00275 */ 00276 virtual void whitelistFromBondTable(Gap::Whitelist_t* whitelist) { 00277 (void)whitelist; 00278 } 00279 00280 //////////////////////////////////////////////////////////////////////////// 00281 // Encryption 00282 // 00283 00284 /** 00285 * Inform the device of the encryption state of a given link. 00286 * 00287 * @param[in] connectionHandle connection connectionHandle 00288 * @param[in] result encryption state of the link 00289 */ 00290 virtual void linkEncryptionResult(ble::connection_handle_t connectionHandle, ble::link_encryption_t result) { 00291 (void)connectionHandle; 00292 (void)result; 00293 } 00294 00295 //////////////////////////////////////////////////////////////////////////// 00296 // MITM 00297 // 00298 00299 /** 00300 * Display the given passkey on the local device. 00301 * 00302 * @param[in] connectionHandle connection connectionHandle 00303 * @param[in] passkey 6 digit passkey to be displayed 00304 */ 00305 virtual void passkeyDisplay(ble::connection_handle_t connectionHandle, const SecurityManager::Passkey_t passkey) { 00306 (void)connectionHandle; 00307 (void)passkey; 00308 } 00309 00310 /** 00311 * Indicate to the application that a confirmation is required. This is used 00312 * when the device does not have a keyboard but has a yes/no button. The device 00313 * displays numbers on its display in response to passkeyDisplay and the user 00314 * checks if they are the same on both devices. The application should proceed 00315 * by supplying the confirmation using the confirmationEntered function. 00316 * 00317 * @param[in] connectionHandle connection connectionHandle 00318 */ 00319 virtual void confirmationRequest(ble::connection_handle_t connectionHandle) { 00320 (void)connectionHandle; 00321 } 00322 00323 /** 00324 * Indicate to the application that a passkey is required. The application should 00325 * proceed by supplying the passkey through the passkeyEntered function. 00326 * 00327 * @param[in] connectionHandle connection connectionHandle 00328 */ 00329 virtual void passkeyRequest(ble::connection_handle_t connectionHandle) { 00330 (void)connectionHandle; 00331 } 00332 00333 /** 00334 * Notify the application that a key was pressed by the peer during passkey entry. 00335 * 00336 * @param[in] connectionHandle connection connectionHandle 00337 * @param[in] keypress type of keypress event 00338 */ 00339 virtual void keypressNotification(ble::connection_handle_t connectionHandle, SecurityManager::Keypress_t keypress) { 00340 (void)connectionHandle; 00341 (void)keypress; 00342 } 00343 00344 /** 00345 * Indicate to the application it needs to return legacy pairing OOB to the stack. 00346 * 00347 * @param[in] connectionHandle connection connectionHandle 00348 */ 00349 virtual void legacyPairingOobRequest(ble::connection_handle_t connectionHandle) { 00350 (void)connectionHandle; 00351 } 00352 00353 /** 00354 * Indicate that the application needs to send legacy pairing OOB data to the peer. 00355 * 00356 * @param[in] address address that will be used in the pairing 00357 * @param[in] temporaryKey temporary key to be used in legacy pairing 00358 */ 00359 virtual void legacyPairingOobGenerated(const ble::address_t *address, 00360 const ble::oob_tk_t *temporaryKey) { 00361 (void)address; 00362 (void)temporaryKey; 00363 } 00364 00365 /** 00366 * Indicate that the application needs to send secure connections OOB data to the peer. 00367 * 00368 * @param[in] address address that will be used in the pairing 00369 * @param[in] random random number used to generate the confirmation 00370 * @param[in] confirm confirmation value to be use for authentication 00371 * in secure connections pairing 00372 */ 00373 virtual void oobGenerated(const ble::address_t *address, 00374 const ble::oob_lesc_value_t *random, 00375 const ble::oob_confirm_t *confirm) { 00376 (void)address; 00377 (void)random; 00378 (void)confirm; 00379 } 00380 00381 //////////////////////////////////////////////////////////////////////////// 00382 // Keys 00383 // 00384 00385 /** 00386 * Deliver the signing key to the application. 00387 * 00388 * @param[in] connectionHandle connection connectionHandle 00389 * @param[in] csrk signing key, pointer only valid during call 00390 * @param[in] authenticated indicates if the signing key is authenticated 00391 */ 00392 virtual void signingKey(ble::connection_handle_t connectionHandle, const ble::csrk_t *csrk, bool authenticated) { 00393 (void)connectionHandle; 00394 (void)csrk; 00395 (void)authenticated; 00396 } 00397 }; 00398 00399 /* 00400 * The following functions are meant to be overridden in the platform-specific sub-class. 00401 */ 00402 public: 00403 //////////////////////////////////////////////////////////////////////////// 00404 // SM lifecycle management 00405 // 00406 00407 /** 00408 * Enable the BLE stack's Security Manager. The Security Manager implements 00409 * the actual cryptographic algorithms and protocol exchanges that allow two 00410 * devices to securely exchange data and privately detect each other. 00411 * Calling this API is a prerequisite for encryption and pairing (bonding). 00412 * 00413 * @param[in] enableBonding Allow for bonding. 00414 * @param[in] requireMITM Require protection for man-in-the-middle attacks. 00415 * @param[in] iocaps To specify the I/O capabilities of this peripheral, 00416 * such as availability of a display or keyboard, to 00417 * support out-of-band exchanges of security data. 00418 * @param[in] passkey To specify a static passkey. 00419 * @param[in] signing Generate and distribute signing key during pairing 00420 * 00421 * @return BLE_ERROR_NONE on success. 00422 */ 00423 virtual ble_error_t init(bool enableBonding = true, 00424 bool requireMITM = true, 00425 SecurityIOCapabilities_t iocaps = IO_CAPS_NONE, 00426 const Passkey_t passkey = NULL, 00427 bool signing = true) { 00428 /* Avoid compiler warnings about unused variables. */ 00429 (void)enableBonding; 00430 (void)requireMITM; 00431 (void)iocaps; 00432 (void)passkey; 00433 00434 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00435 } 00436 00437 /** 00438 * Notify all registered onShutdown callbacks that the SecurityManager is 00439 * about to be shutdown and clear all SecurityManager state of the 00440 * associated object. 00441 * 00442 * This function is meant to be overridden in the platform-specific 00443 * sub-class. Nevertheless, the sub-class is only expected to reset its 00444 * state and not the data held in SecurityManager members. This shall be 00445 * achieved by a call to SecurityManager::reset() from the sub-class' 00446 * reset() implementation. 00447 * 00448 * @return BLE_ERROR_NONE on success. 00449 */ 00450 virtual ble_error_t reset(void) { 00451 /* Notify that the instance is about to shutdown */ 00452 shutdownCallChain.call(this); 00453 shutdownCallChain.clear(); 00454 eventHandler = &defaultEventHandler; 00455 00456 return BLE_ERROR_NONE; 00457 } 00458 00459 /** 00460 * Normally all bonding information is lost when device is reset, this requests that the stack 00461 * attempts to save the information and reload it during initialisation. This is not guaranteed. 00462 * 00463 * @param[in] enable if true the stack will attempt to preserve bonding information on reset. 00464 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00465 */ 00466 virtual ble_error_t preserveBondingStateOnReset(bool enable) { 00467 /* Avoid compiler warnings about unused variables */ 00468 (void) enable; 00469 00470 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00471 } 00472 00473 //////////////////////////////////////////////////////////////////////////// 00474 // List management 00475 // 00476 00477 /** 00478 * Delete all peer device context and all related bonding information from 00479 * the database within the security manager. 00480 * 00481 * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. 00482 * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization or 00483 * application registration. 00484 */ 00485 virtual ble_error_t purgeAllBondingState(void) { 00486 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00487 } 00488 00489 /** 00490 * Create a list of addresses from all peers in the bond table and generate 00491 * an event which returns it as a whitelist. Pass in the container for the whitelist. 00492 * This will be returned by the event. 00493 * 00494 * @param[in] whitelist Preallocated whitelist which will be filled up to its capacity. 00495 * If whitelist already contains entries this will be appended to. 00496 * Do not access the whitelist until callback has been called, 00497 * returning the filled whitelist. 00498 * 00499 * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure 00500 */ 00501 virtual ble_error_t generateWhitelistFromBondTable(Gap::Whitelist_t *whitelist) const { 00502 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00503 } 00504 00505 //////////////////////////////////////////////////////////////////////////// 00506 // Pairing 00507 // 00508 00509 /** 00510 * Request pairing with the peer. Called by the master. 00511 * @note Slave can call requestAuthentication or setLinkEncryption to achieve security. 00512 * 00513 * @param[in] connectionHandle Handle to identify the connection. 00514 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00515 */ 00516 virtual ble_error_t requestPairing(ble::connection_handle_t connectionHandle) { 00517 (void) connectionHandle; 00518 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00519 } 00520 00521 /** 00522 * Accept the pairing request. Called as a result of pairingRequest being called 00523 * on the event handler. 00524 * 00525 * @param[in] connectionHandle Handle to identify the connection. 00526 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00527 */ 00528 virtual ble_error_t acceptPairingRequest(ble::connection_handle_t connectionHandle) { 00529 (void) connectionHandle; 00530 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00531 } 00532 00533 /** 00534 * Reject pairing request if the local device is the slave or cancel an outstanding 00535 * pairing request if master. 00536 * 00537 * @param[in] connectionHandle Handle to identify the connection. 00538 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00539 */ 00540 virtual ble_error_t cancelPairingRequest(ble::connection_handle_t connectionHandle) { 00541 (void) connectionHandle; 00542 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00543 } 00544 00545 /** 00546 * Tell the stack whether the application needs to authorise pairing requests or should 00547 * they be automatically accepted. 00548 * 00549 * @param[in] required If set to true, pairingRequest in the event handler will 00550 * will be called and will require an action from the application 00551 * to continue with pairing by calling acceptPairingRequest 00552 * or cancelPairingRequest if the user wishes to reject it. 00553 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00554 */ 00555 virtual ble_error_t setPairingRequestAuthorisation(bool required = true) { 00556 (void) required; 00557 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00558 } 00559 00560 //////////////////////////////////////////////////////////////////////////// 00561 // Feature support 00562 // 00563 00564 /** 00565 * Allow of disallow the use of legacy pairing in case the application only wants 00566 * to force the use of Secure Connections. If legacy pairing is disallowed and either 00567 * side doesn't support Secure Connections the pairing will fail. 00568 * 00569 * @param[out] allow If true legacy pairing will be used if either side doesn't support Secure Connections. 00570 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00571 */ 00572 virtual ble_error_t allowLegacyPairing(bool allow = true) { 00573 (void) allow; 00574 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00575 } 00576 00577 /** 00578 * Check if the Secure Connections feature is supported by the stack and controller. 00579 * 00580 * @param[out] enabled true if SC are supported 00581 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00582 */ 00583 virtual ble_error_t getSecureConnectionsSupport(bool *enabled) { 00584 (void) enabled; 00585 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00586 } 00587 00588 //////////////////////////////////////////////////////////////////////////// 00589 // Security settings 00590 // 00591 00592 /** 00593 * Set the IO capability of the local device. 00594 * 00595 * @param[in] iocaps type of IO capabilities available on the local device 00596 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00597 */ 00598 virtual ble_error_t setIoCapability(SecurityIOCapabilities_t iocaps) { 00599 (void) iocaps; 00600 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00601 } 00602 00603 /** 00604 * Set the passkey that is displayed on the local device instead of using 00605 * a randomly generated one 00606 * 00607 * @param[in] passkey ASCII string of 6 digits 00608 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00609 */ 00610 virtual ble_error_t setDisplayPasskey(const Passkey_t passkey) { 00611 (void) passkey; 00612 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00613 } 00614 00615 /** 00616 * Set the security mode on a connection. Useful for elevating the security mode 00617 * once certain conditions are met, e.g., a particular service is found. 00618 * 00619 * @param[in] connectionHandle Handle to identify the connection. 00620 * @param[in] securityMode Requested security mode. 00621 * 00622 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00623 */ 00624 virtual ble_error_t setLinkSecurity(ble::connection_handle_t connectionHandle, SecurityMode_t securityMode) { 00625 /* Avoid compiler warnings about unused variables. */ 00626 (void)connectionHandle; 00627 (void)securityMode; 00628 00629 return BLE_ERROR_NOT_IMPLEMENTED; 00630 } 00631 00632 /** 00633 * Set whether or not we want to send and receive keypress notifications 00634 * during passkey entry. 00635 * 00636 * @param[in] enabled if true pairing will try to enable keypress notifications 00637 * (dependent on other side supporting it) 00638 * 00639 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00640 */ 00641 virtual ble_error_t setKeypressNotification(bool enabled = true) { 00642 (void)enabled; 00643 return BLE_ERROR_NOT_IMPLEMENTED; 00644 } 00645 00646 /** 00647 * Request generation and exchange of signing keys so that packet signing can be utilised 00648 * on this connection. 00649 * @note This does not generate a signingKey event. Use getSigningKey for that. 00650 * 00651 * @param[in] connectionHandle Handle to identify the connection. 00652 * @param[in] enabled If set to true, signing keys will be exchanged 00653 * during subsequent pairing. 00654 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00655 */ 00656 virtual ble_error_t enableSigning(ble::connection_handle_t connectionHandle, bool enabled = true) { 00657 (void) enabled; 00658 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00659 } 00660 00661 /** 00662 * Give a hint to the stack that the master/slave role might change in the future. 00663 * 00664 * @param[in] enable If set to true it hints the roles are likely to swap in the future. 00665 * 00666 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00667 */ 00668 virtual ble_error_t setHintFutureRoleReversal(bool enable = true) { 00669 (void)enable; 00670 return BLE_ERROR_NOT_IMPLEMENTED; 00671 } 00672 00673 //////////////////////////////////////////////////////////////////////////// 00674 // Encryption 00675 // 00676 00677 /** 00678 * Current state of encryption on the link. 00679 * 00680 * @param[in] connectionHandle Handle to identify the connection. 00681 * @param[out] encryption 00682 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00683 */ 00684 virtual ble_error_t getLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t *encryption) { 00685 (void)connectionHandle; 00686 (void)encryption; 00687 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00688 } 00689 00690 /** 00691 * Enabled or disable encryption on the link. The result of this request will be indicated 00692 * by a call to linkEncryptionResult in the event handler when the action is completed. 00693 * 00694 * @param[in] connectionHandle Handle to identify the connection. 00695 * @param[in] encryption encryption state requested 00696 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00697 */ 00698 virtual ble_error_t setLinkEncryption(ble::connection_handle_t connectionHandle, ble::link_encryption_t encryption) { 00699 (void)connectionHandle; 00700 (void)encryption; 00701 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00702 } 00703 00704 /** 00705 * Set the requirements for encryption key size. If the peer cannot comply with the requirements 00706 * paring will fail. 00707 * 00708 * @param[in] minimumByteSize Smallest allowed encryption key size in bytes. (no smaller than 7) 00709 * @param[in] maximumByteSize Largest allowed encryption key size in bytes. (no larger than 16) 00710 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00711 */ 00712 virtual ble_error_t setEncryptionKeyRequirements(uint8_t minimumByteSize, uint8_t maximumByteSize) { 00713 (void) minimumByteSize; 00714 (void) maximumByteSize; 00715 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00716 } 00717 00718 //////////////////////////////////////////////////////////////////////////// 00719 // Authentication 00720 // 00721 00722 /** 00723 * Request that the link be authenticated (keys with MITM protection). This might trigger encryption 00724 * or pairing/re-pairing. The success will be indicated through an event indicating security level change. 00725 * 00726 * @param[in] connectionHandle Handle to identify the connection. 00727 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00728 */ 00729 virtual ble_error_t requestAuthentication(ble::connection_handle_t connectionHandle) { 00730 (void) connectionHandle; 00731 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00732 } 00733 00734 //////////////////////////////////////////////////////////////////////////// 00735 // MITM 00736 // 00737 00738 /** 00739 * Enable OOB data usage during paring. 00740 * 00741 * @param[in] connectionHandle Handle to identify the connection. 00742 * @param[in] useOOB If set to true, authenticate using OOB data. 00743 * @param[in] OOBProvidesMITM If set to true keys exchanged during pairing using OOB data 00744 * will provide MITM protection. This indicates that the form 00745 * of exchange used by the OOB data itself provides MITM protection. 00746 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00747 */ 00748 virtual ble_error_t setOOBDataUsage(ble::connection_handle_t connectionHandle, bool useOOB, bool OOBProvidesMITM = true) { 00749 /* Avoid compiler warnings about unused variables */ 00750 (void) connectionHandle; 00751 (void) useOOB; 00752 (void) OOBProvidesMITM; 00753 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00754 } 00755 00756 /** 00757 * Report to the stack if the passkey matches or not. Used during pairing to provide MITM protection. 00758 * 00759 * @param[in] connectionHandle Handle to identify the connection. 00760 * @param[in] confirmation True value indicates the passkey displayed matches. 00761 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00762 */ 00763 virtual ble_error_t confirmationEntered(ble::connection_handle_t connectionHandle, bool confirmation) { 00764 (void) connectionHandle; 00765 (void) confirmation; 00766 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00767 } 00768 00769 /** 00770 * Supply the stack with the user entered passkey. 00771 * 00772 * @param[in] connectionHandle Handle to identify the connection. 00773 * @param[in] passkey ASCII string of digits entered by the user. 00774 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00775 */ 00776 virtual ble_error_t passkeyEntered(ble::connection_handle_t connectionHandle, Passkey_t passkey) { 00777 (void) connectionHandle; 00778 (void) passkey; 00779 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00780 } 00781 00782 /** 00783 * Send a notification to the peer that the user pressed a key on the local device. 00784 * @note This will only be delivered if the keypress notifications have been enabled during pairing. 00785 * 00786 * @param[in] connectionHandle Handle to identify the connection. 00787 * @param[in] keypress Type of keypress event. 00788 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00789 */ 00790 virtual ble_error_t sendKeypressNotification(ble::connection_handle_t connectionHandle, Keypress_t keypress) { 00791 (void) connectionHandle; 00792 (void) keypress; 00793 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00794 } 00795 00796 /** 00797 * Supply the stack with the OOB data for legacy connections. 00798 * 00799 * @param[in] address address of the peer device this data comes from 00800 * @param[in] tk pointer to out of band data received containing the temporary key. 00801 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00802 */ 00803 virtual ble_error_t legacyPairingOobReceived(const ble::address_t *address, const ble::oob_tk_t *tk) { 00804 (void) address; 00805 (void) tk; 00806 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00807 } 00808 00809 /** 00810 * Supply the stack with the OOB data for secure connections. 00811 * 00812 * @param[in] address address of the peer device this data comes from 00813 * @param[in] random random number used to generate the confirmation 00814 * @param[in] confirm confirmation value to be use for authentication 00815 * in secure connections pairing 00816 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00817 */ 00818 virtual ble_error_t oobReceived(const ble::address_t *address, const ble::oob_lesc_value_t *random, const ble::oob_confirm_t *confirm) { 00819 (void) address; 00820 (void) random; 00821 (void) confirm; 00822 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00823 } 00824 00825 //////////////////////////////////////////////////////////////////////////// 00826 // Keys 00827 // 00828 00829 /** 00830 * Retrieves a signing key through a signingKey event. 00831 * If a signing key is not present, pairing/authentication will be attempted. 00832 * @note This will attempt to retrieve the key even if enableSigning hasn't been called prior to pairing. 00833 * 00834 * @param[in] connectionHandle Handle to identify the connection. 00835 * @param[in] authenticated Whether the signing key needs to be authenticated 00836 * (provide MITM protection). 00837 * 00838 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00839 */ 00840 virtual ble_error_t getSigningKey(ble::connection_handle_t connectionHandle, bool authenticated) { 00841 (void)connectionHandle; 00842 (void)authenticated; 00843 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00844 } 00845 00846 /* Event callback handlers. */ 00847 public: 00848 /** 00849 * Setup a callback to be invoked to notify the user application that the 00850 * SecurityManager instance is about to shutdown (possibly as a result of a call 00851 * to BLE::shutdown()). 00852 * 00853 * @note It is possible to chain together multiple onShutdown callbacks 00854 * (potentially from different modules of an application) to be notified 00855 * before the SecurityManager is shutdown. 00856 * 00857 * @note It is also possible to set up a callback into a member function of 00858 * some object. 00859 * 00860 * @note It is possible to unregister a callback using onShutdown().detach(callback) 00861 */ 00862 void onShutdown(const SecurityManagerShutdownCallback_t & callback) { 00863 shutdownCallChain.add(callback); 00864 } 00865 template <typename T> 00866 void onShutdown(T *objPtr, void (T::*memberPtr)(const SecurityManager *)) { 00867 shutdownCallChain.add(objPtr, memberPtr); 00868 } 00869 00870 /** 00871 * Provide access to the callchain of shutdown event callbacks. 00872 * It is possible to register callbacks using onShutdown().add(callback). 00873 * It is possible to unregister callbacks using onShutdown().detach(callback). 00874 * 00875 * @return The shutdown event callbacks chain 00876 */ 00877 SecurityManagerShutdownCallbackChain_t & onShutdown() { 00878 return shutdownCallChain; 00879 } 00880 00881 /** 00882 * Assign the event handler implementation that will be used by the stack to signal events 00883 * back to the application. 00884 * 00885 * @param[in] handler Event Handler interface implementation. 00886 */ 00887 virtual void setSecurityManagerEventHandler(EventHandler* handler) { 00888 if (handler) { 00889 eventHandler = handler; 00890 } else { 00891 eventHandler = &defaultEventHandler; 00892 } 00893 } 00894 00895 protected: 00896 SecurityManager() { 00897 eventHandler = &defaultEventHandler; 00898 } 00899 00900 virtual ~SecurityManager() { }; 00901 00902 public: 00903 /** 00904 * @deprecated use generateWhitelistFromBondTable instead 00905 * 00906 * Get a list of addresses from all peers in the bond table. 00907 * 00908 * @param[in,out] addresses 00909 * (on input) addresses.capacity contains the maximum 00910 * number of addresses to be returned. 00911 * (on output) The populated table with copies of the 00912 * addresses in the implementation's whitelist. 00913 * 00914 * @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure. 00915 * @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization or 00916 * application registration. 00917 */ 00918 virtual ble_error_t getAddressesFromBondTable (Gap::Whitelist_t &addresses) const { 00919 /* Avoid compiler warnings about unused variables */ 00920 (void) addresses; 00921 return BLE_ERROR_NOT_IMPLEMENTED; /* Requesting action from porters: override this API if security is supported. */ 00922 } 00923 00924 /** 00925 * @deprecated 00926 * 00927 * Get the security status of a connection. 00928 * 00929 * @param[in] connectionHandle Handle to identify the connection. 00930 * @param[out] securityStatus Security status. 00931 * 00932 * @return BLE_ERROR_NONE or appropriate error code indicating the failure reason. 00933 */ 00934 ble_error_t getLinkSecurity (ble::connection_handle_t connectionHandle, LinkSecurityStatus_t *securityStatus) { 00935 ble::link_encryption_t encryption(ble::link_encryption_t::NOT_ENCRYPTED); 00936 ble_error_t status = getLinkEncryption(connectionHandle, &encryption); 00937 /* legacy support limits the return values */ 00938 if (encryption.value() == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { 00939 *securityStatus = ENCRYPTED; 00940 } else { 00941 *securityStatus = (LinkSecurityStatus_t)encryption.value(); 00942 } 00943 00944 return status; 00945 } 00946 00947 /** 00948 * @deprecated 00949 * 00950 * To indicate that a security procedure for the link has started. 00951 */ 00952 virtual void onSecuritySetupInitiated (SecuritySetupInitiatedCallback_t callback) { 00953 defaultEventHandler.securitySetupInitiatedCallback = callback; 00954 } 00955 00956 /** 00957 * @deprecated 00958 * 00959 * To indicate that the security procedure for the link has completed. 00960 */ 00961 virtual void onSecuritySetupCompleted (SecuritySetupCompletedCallback_t callback) { 00962 defaultEventHandler.securitySetupCompletedCallback = callback; 00963 } 00964 00965 /** 00966 * @deprecated 00967 * 00968 * To indicate that the link with the peer is secured. For bonded devices, 00969 * subsequent reconnections with a bonded peer will result only in this callback 00970 * when the link is secured; setup procedures will not occur (unless the 00971 * bonding information is either lost or deleted on either or both sides). 00972 */ 00973 virtual void onLinkSecured (LinkSecuredCallback_t callback) { 00974 defaultEventHandler.linkSecuredCallback = callback; 00975 } 00976 00977 /** 00978 * @deprecated 00979 * 00980 * To indicate that device context is stored persistently. 00981 */ 00982 virtual void onSecurityContextStored (HandleSpecificEvent_t callback) { 00983 defaultEventHandler.securityContextStoredCallback = callback; 00984 } 00985 00986 /** @deprecated 00987 * 00988 * To set the callback for when the passkey needs to be displayed on a peripheral with DISPLAY capability. 00989 */ 00990 virtual void onPasskeyDisplay (PasskeyDisplayCallback_t callback) { 00991 defaultEventHandler.passkeyDisplayCallback = callback; 00992 } 00993 00994 /* Entry points for the underlying stack to report events back to the user. */ 00995 public: 00996 /** @deprecated */ 00997 void processSecuritySetupInitiatedEvent (ble::connection_handle_t connectionHandle, bool allowBonding, bool requireMITM, SecurityIOCapabilities_t iocaps) { 00998 if (defaultEventHandler.securitySetupInitiatedCallback) { 00999 defaultEventHandler.securitySetupInitiatedCallback(connectionHandle, allowBonding, requireMITM, iocaps); 01000 } 01001 } 01002 /** @deprecated */ 01003 void processSecuritySetupCompletedEvent (ble::connection_handle_t connectionHandle, SecurityCompletionStatus_t status) { 01004 eventHandler->pairingResult(connectionHandle, status); 01005 } 01006 /** @deprecated */ 01007 void processLinkSecuredEvent (ble::connection_handle_t connectionHandle, SecurityMode_t securityMode) { 01008 if (securityMode == SECURITY_MODE_ENCRYPTION_NO_MITM) { 01009 eventHandler->linkEncryptionResult(connectionHandle, ble::link_encryption_t::ENCRYPTED); 01010 } else { 01011 eventHandler->linkEncryptionResult(connectionHandle, ble::link_encryption_t::NOT_ENCRYPTED); 01012 } 01013 } 01014 /** @deprecated */ 01015 void processSecurityContextStoredEvent (ble::connection_handle_t connectionHandle) { 01016 if (defaultEventHandler.securityContextStoredCallback) { 01017 defaultEventHandler.securityContextStoredCallback(connectionHandle); 01018 } 01019 } 01020 /** @deprecated */ 01021 void processPasskeyDisplayEvent (ble::connection_handle_t connectionHandle, const Passkey_t passkey) { 01022 eventHandler->passkeyDisplay(connectionHandle, passkey); 01023 } 01024 01025 private: 01026 /* Legacy compatibility with old callbacks (from both sides so any 01027 * combination of new and old works) */ 01028 class LegacyEventHandler : public EventHandler { 01029 public: 01030 LegacyEventHandler() : 01031 securitySetupInitiatedCallback(), 01032 securitySetupCompletedCallback(), 01033 linkSecuredCallback(), 01034 securityContextStoredCallback(), 01035 passkeyDisplayCallback() { }; 01036 01037 virtual void pairingResult(ble::connection_handle_t connectionHandle, SecurityCompletionStatus_t result) { 01038 if (securitySetupCompletedCallback) { 01039 securitySetupCompletedCallback(connectionHandle, result); 01040 } 01041 } 01042 01043 virtual void linkEncryptionResult(ble::connection_handle_t connectionHandle, ble::link_encryption_t result) { 01044 if (linkSecuredCallback) { 01045 SecurityManager::SecurityMode_t securityMode; 01046 if (result == ble::link_encryption_t::ENCRYPTED) { 01047 securityMode = SECURITY_MODE_ENCRYPTION_NO_MITM; 01048 } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) { 01049 securityMode = SECURITY_MODE_ENCRYPTION_WITH_MITM; 01050 } else { 01051 securityMode = SECURITY_MODE_ENCRYPTION_OPEN_LINK; 01052 } 01053 linkSecuredCallback(connectionHandle, securityMode); 01054 } 01055 }; 01056 01057 virtual void passkeyDisplay(ble::connection_handle_t connectionHandle, const SecurityManager::Passkey_t passkey) { 01058 if (passkeyDisplayCallback) { 01059 passkeyDisplayCallback(connectionHandle, passkey); 01060 } 01061 }; 01062 01063 SecurityManager::SecuritySetupInitiatedCallback_t securitySetupInitiatedCallback; 01064 SecurityManager::SecuritySetupCompletedCallback_t securitySetupCompletedCallback; 01065 SecurityManager::LinkSecuredCallback_t linkSecuredCallback; 01066 SecurityManager::HandleSpecificEvent_t securityContextStoredCallback; 01067 SecurityManager::PasskeyDisplayCallback_t passkeyDisplayCallback; 01068 }; 01069 01070 private: 01071 SecurityManagerShutdownCallbackChain_t shutdownCallChain; 01072 01073 protected: 01074 EventHandler* eventHandler; 01075 LegacyEventHandler defaultEventHandler; 01076 }; 01077 01078 #endif /*SECURITY_MANAGER_H_*/
Generated on Tue Jul 12 2022 14:24:34 by
