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.
Fork of nRF51822 by
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, ¶ms); 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 }
Generated on Fri Jul 15 2022 12:51:28 by
1.7.2
