Nordic stack and drivers for the mbed BLE API. Version to work around build bug.

Dependents:   microbit_rubber_ducky microbit_mouse_BLE microbit_mouse_BLE_daybreak_version microbit_presenter

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers btle_security.cpp Source File

btle_security.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 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 #include "btle.h"
00018 
00019 #include "nRF5xn.h"
00020 
00021 extern "C" {
00022 #include "pstorage.h "
00023 #include "device_manager.h "
00024 #include "id_manager.h"
00025 }
00026 
00027 #include "btle_security.h"
00028 
00029 static dm_application_instance_t applicationInstance;
00030 static bool                      initialized = false;
00031 static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
00032 
00033 // default security parameters
00034 static ble_gap_sec_params_t securityParameters = {
00035     .bond          = true,         /**< Perform bonding. */
00036     .mitm          = true,         /**< Man In The Middle protection required. */
00037     .io_caps       = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
00038     .oob           = 0,            /**< Out Of Band data available. */
00039     .min_key_size  = 16,           /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
00040     .max_key_size  = 16,           /**< Maximum encryption key size in octets between min_key_size and 16. */
00041     .kdist_periph  = {
00042       .enc  = 1,                   /**< Long Term Key and Master Identification. */
00043       .id   = 1,                   /**< Identity Resolving Key and Identity Address Information. */
00044       .sign = 1,                   /**< Connection Signature Resolving Key. */
00045     },                             /**< Key distribution bitmap: keys that the peripheral device will distribute. */
00046 };
00047 
00048 bool
00049 btle_hasInitializedSecurity(void)
00050 {
00051     return initialized;
00052 }
00053 
00054 ble_error_t
00055 btle_initializeSecurity(bool                                      enableBonding,
00056                         bool                                      requireMITM,
00057                         SecurityManager::SecurityIOCapabilities_t iocaps,
00058                         const SecurityManager::Passkey_t          passkey)
00059 {
00060     /* guard against multiple initializations */
00061     if (initialized) {
00062         return BLE_ERROR_NONE;
00063     }
00064 
00065     if (pstorage_init() != NRF_SUCCESS) {
00066         return BLE_ERROR_UNSPECIFIED;
00067     }
00068 
00069     ret_code_t rc;
00070     if (passkey) {
00071         ble_opt_t opts;
00072         opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
00073         if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
00074             switch (rc) {
00075                 case BLE_ERROR_INVALID_CONN_HANDLE:
00076                 case NRF_ERROR_INVALID_ADDR:
00077                 case NRF_ERROR_INVALID_PARAM:
00078                 default:
00079                     return BLE_ERROR_INVALID_PARAM;
00080                 case NRF_ERROR_INVALID_STATE:
00081                     return BLE_ERROR_INVALID_STATE;
00082                 case NRF_ERROR_BUSY:
00083                     return BLE_STACK_BUSY;
00084             }
00085         }
00086     }
00087 
00088     dm_init_param_t dm_init_param = {
00089         .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */
00090     };
00091     if (dm_init(&dm_init_param) != NRF_SUCCESS) {
00092         return BLE_ERROR_UNSPECIFIED;
00093     }
00094 
00095     // update default security parameters with function call parameters
00096     securityParameters.bond = enableBonding;
00097     securityParameters.mitm = requireMITM;
00098     securityParameters.io_caps = iocaps;
00099 
00100     const dm_application_param_t dm_param = {
00101         .evt_handler  = dm_handler,
00102         .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
00103         .sec_param    = securityParameters
00104     };
00105 
00106     if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
00107         switch (rc) {
00108             case NRF_ERROR_INVALID_STATE:
00109                 return BLE_ERROR_INVALID_STATE;
00110             case NRF_ERROR_NO_MEM:
00111                 return BLE_ERROR_NO_MEM;
00112             default:
00113                 return BLE_ERROR_UNSPECIFIED;
00114         }
00115     }
00116 
00117     initialized = true;
00118     return BLE_ERROR_NONE;
00119 }
00120 
00121 ble_error_t
00122 btle_purgeAllBondingState(void)
00123 {
00124     ret_code_t rc;
00125     if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) {
00126         return BLE_ERROR_NONE;
00127     }
00128 
00129     switch (rc) {
00130         case NRF_ERROR_INVALID_STATE:
00131             return BLE_ERROR_INVALID_STATE;
00132         case NRF_ERROR_NO_MEM:
00133             return BLE_ERROR_NO_MEM;
00134         default:
00135             return BLE_ERROR_UNSPECIFIED;
00136     }
00137 }
00138 
00139 ble_error_t
00140 btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
00141 {
00142     ret_code_t rc;
00143     dm_handle_t dmHandle = {
00144         .appl_id = applicationInstance,
00145     };
00146     if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) {
00147         if (rc == NRF_ERROR_NOT_FOUND) {
00148             return BLE_ERROR_INVALID_PARAM;
00149         } else {
00150             return BLE_ERROR_UNSPECIFIED;
00151         }
00152     }
00153 
00154     if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast<dm_security_status_t *>(securityStatusP))) != NRF_SUCCESS) {
00155         switch (rc) {
00156             case NRF_ERROR_INVALID_STATE:
00157                 return BLE_ERROR_INVALID_STATE;
00158             case NRF_ERROR_NO_MEM:
00159                 return BLE_ERROR_NO_MEM;
00160             default:
00161                 return BLE_ERROR_UNSPECIFIED;
00162         }
00163     }
00164 
00165     return BLE_ERROR_NONE;
00166 }
00167 
00168 ble_error_t
00169 btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
00170 {
00171     // use default and updated parameters as starting point
00172     // and modify structure based on security mode.
00173     ble_gap_sec_params_t params = securityParameters;
00174 
00175     switch (securityMode) {
00176         case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
00177             /**< Require no protection, open link. */
00178             securityParameters.bond = false;
00179             securityParameters.mitm = false;
00180             break;
00181 
00182         case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
00183             /**< Require encryption, but no MITM protection. */
00184             securityParameters.bond = true;
00185             securityParameters.mitm = false;
00186             break;
00187 
00188         // not yet implemented security modes
00189         case SecurityManager::SECURITY_MODE_NO_ACCESS:
00190         case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
00191             /**< Require encryption and MITM protection. */
00192         case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
00193             /**< Require signing or encryption, but no MITM protection. */
00194         case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
00195             /**< Require signing or encryption, and MITM protection. */
00196         default:
00197             return BLE_ERROR_NOT_IMPLEMENTED;
00198     }
00199 
00200     // update security settings for given connection
00201     uint32_t result = sd_ble_gap_authenticate(connectionHandle, &params);
00202 
00203     if (result == NRF_SUCCESS) {
00204         return BLE_ERROR_NONE;
00205     } else {
00206         return BLE_ERROR_UNSPECIFIED;
00207     }
00208 }
00209 
00210 ret_code_t
00211 dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
00212 {
00213     nRF5xn               &ble             = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
00214     nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
00215 
00216     switch (p_event->event_id) {
00217         case DM_EVT_SECURITY_SETUP: /* started */ {
00218             const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params;
00219             securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle,
00220                                                                                    peerParams->bond,
00221                                                                                    peerParams->mitm,
00222                                                                                    (SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
00223             break;
00224         }
00225         case DM_EVT_SECURITY_SETUP_COMPLETE:
00226             securityManager.
00227                 processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle,
00228                                                    (SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status));
00229             break;
00230         case DM_EVT_LINK_SECURED: {
00231             unsigned securityMode                    = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm;
00232             unsigned level                           = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv;
00233             SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
00234             switch (securityMode) {
00235                 case 1:
00236                     switch (level) {
00237                         case 1:
00238                             resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
00239                             break;
00240                         case 2:
00241                             resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
00242                             break;
00243                         case 3:
00244                             resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
00245                             break;
00246                     }
00247                     break;
00248                 case 2:
00249                     switch (level) {
00250                         case 1:
00251                             resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
00252                             break;
00253                         case 2:
00254                             resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
00255                             break;
00256                     }
00257                     break;
00258             }
00259 
00260             securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode);
00261             break;
00262         }
00263         case DM_EVT_DEVICE_CONTEXT_STORED:
00264             securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle);
00265             break;
00266         default:
00267             break;
00268     }
00269 
00270     return NRF_SUCCESS;
00271 }
00272 
00273 ble_error_t
00274 btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist)
00275 {
00276     if (!btle_hasInitializedSecurity()) {
00277         return BLE_ERROR_INITIALIZATION_INCOMPLETE;
00278     }
00279     ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist);
00280     if (err == NRF_SUCCESS) {
00281         return BLE_ERROR_NONE;
00282     } else if (err == NRF_ERROR_NULL) {
00283         return BLE_ERROR_PARAM_OUT_OF_RANGE;
00284     } else {
00285         return BLE_ERROR_INVALID_STATE;
00286     }
00287 }
00288 
00289 
00290 bool
00291 btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
00292 {
00293     /*
00294      * Use a helper function from the Nordic SDK to test whether the BLE
00295      * address can be generated using the IRK.
00296      */
00297     return im_address_resolve(p_addr, p_irk);
00298 }
00299 
00300 void
00301 btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address)
00302 {
00303     /* Set type to resolvable */
00304     address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
00305 
00306     /*
00307      * Assign a random number to the most significant 3 bytes
00308      * of the address.
00309      */
00310     address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E;
00311     address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F;
00312     address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C;
00313 
00314     /* Calculate the hash and store it in the top half of the address */
00315     ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr);
00316 }