David Kester / nRF51822

Dependents:   GonioTrainer

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 #include "pstorage.h "
00019 #include "nRF51Gap.h"
00020 #include "device_manager.h "
00021 #include "btle_security.h"
00022 
00023 static dm_application_instance_t applicationInstance;
00024 static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
00025 
00026 ble_error_t
00027 btle_initializeSecurity(bool enableBonding, bool requireMITM, Gap::SecurityIOCapabilities_t iocaps, const Gap::Passkey_t passkey)
00028 {
00029     /* guard against multiple initializations */
00030     static bool initialized = false;
00031     if (initialized) {
00032         return BLE_ERROR_NONE;
00033     }
00034 
00035     if (pstorage_init() != NRF_SUCCESS) {
00036         return BLE_ERROR_UNSPECIFIED;
00037     }
00038 
00039     ret_code_t rc;
00040     if (passkey) {
00041         ble_opt_t opts;
00042         opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
00043         if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
00044             switch (rc) {
00045                 case BLE_ERROR_INVALID_CONN_HANDLE:
00046                 case NRF_ERROR_INVALID_ADDR:
00047                 case NRF_ERROR_INVALID_PARAM:
00048                 default:
00049                     return BLE_ERROR_INVALID_PARAM;
00050                 case NRF_ERROR_INVALID_STATE:
00051                     return BLE_ERROR_INVALID_STATE;
00052                 case NRF_ERROR_BUSY:
00053                     return BLE_STACK_BUSY;
00054             }
00055         }
00056     }
00057 
00058     dm_init_param_t dm_init_param = {
00059         .clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */
00060     };
00061     if (dm_init(&dm_init_param) != NRF_SUCCESS) {
00062         return BLE_ERROR_UNSPECIFIED;
00063     }
00064 
00065     const dm_application_param_t dm_param = {
00066         .evt_handler  = dm_handler,
00067         .service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
00068         .sec_param    = {
00069             .bond          = enableBonding,/**< Perform bonding. */
00070             .mitm          = requireMITM,  /**< Man In The Middle protection required. */
00071             .io_caps       = iocaps,       /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
00072             .oob           = 0,            /**< Out Of Band data available. */
00073             .min_key_size  = 16,           /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
00074             .max_key_size  = 16,           /**< Maximum encryption key size in octets between min_key_size and 16. */
00075             .kdist_periph  = {
00076               .enc  = 1,                     /**< Long Term Key and Master Identification. */
00077               .id   = 1,                     /**< Identity Resolving Key and Identity Address Information. */
00078               .sign = 1,                     /**< Connection Signature Resolving Key. */
00079             },                             /**< Key distribution bitmap: keys that the peripheral device will distribute. */
00080         }
00081     };
00082 
00083     if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
00084         switch (rc) {
00085             case NRF_ERROR_INVALID_STATE:
00086                 return BLE_ERROR_INVALID_STATE;
00087             case NRF_ERROR_NO_MEM:
00088                 return BLE_ERROR_NO_MEM;
00089             default:
00090                 return BLE_ERROR_UNSPECIFIED;
00091         }
00092     }
00093 
00094     initialized = true;
00095     return BLE_ERROR_NONE;
00096 }
00097 
00098 ble_error_t
00099 btle_purgeAllBondingState(void)
00100 {
00101     ret_code_t rc;
00102     if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) {
00103         return BLE_ERROR_NONE;
00104     }
00105 
00106     switch (rc) {
00107         case NRF_ERROR_INVALID_STATE:
00108             return BLE_ERROR_INVALID_STATE;
00109         case NRF_ERROR_NO_MEM:
00110             return BLE_ERROR_NO_MEM;
00111         default:
00112             return BLE_ERROR_UNSPECIFIED;
00113     }
00114 }
00115 
00116 ble_error_t
00117 btle_getLinkSecurity(Gap::Handle_t connectionHandle, Gap::LinkSecurityStatus_t *securityStatusP)
00118 {
00119     ret_code_t rc;
00120     dm_handle_t dmHandle = {
00121         .appl_id = applicationInstance,
00122     };
00123     if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) {
00124         if (rc == NRF_ERROR_NOT_FOUND) {
00125             return BLE_ERROR_INVALID_PARAM;
00126         } else {
00127             return BLE_ERROR_UNSPECIFIED;
00128         }
00129     }
00130 
00131     if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast<dm_security_status_t *>(securityStatusP))) != NRF_SUCCESS) {
00132         switch (rc) {
00133             case NRF_ERROR_INVALID_STATE:
00134                 return BLE_ERROR_INVALID_STATE;
00135             case NRF_ERROR_NO_MEM:
00136                 return BLE_ERROR_NO_MEM;
00137             default:
00138                 return BLE_ERROR_UNSPECIFIED;
00139         }
00140     }
00141 
00142     return BLE_ERROR_NONE;
00143 }
00144 
00145 ret_code_t
00146 dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
00147 {
00148     switch (p_event->event_id) {
00149         case DM_EVT_SECURITY_SETUP: /* started */ {
00150             const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params;
00151             nRF51Gap::getInstance().processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle,
00152                                                                            peerParams->bond,
00153                                                                            peerParams->mitm,
00154                                                                            (Gap::SecurityIOCapabilities_t)peerParams->io_caps);
00155             break;
00156         }
00157         case DM_EVT_SECURITY_SETUP_COMPLETE:
00158             nRF51Gap::getInstance().processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle,
00159                                                                            (Gap::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status));
00160             break;
00161         case DM_EVT_LINK_SECURED: {
00162             unsigned securityMode                    = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm;
00163             unsigned level                           = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv;
00164             Gap::SecurityMode_t resolvedSecurityMode = Gap::SECURITY_MODE_NO_ACCESS;
00165             switch (securityMode) {
00166                 case 1:
00167                     switch (level) {
00168                         case 1:
00169                             resolvedSecurityMode = Gap::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
00170                             break;
00171                         case 2:
00172                             resolvedSecurityMode = Gap::SECURITY_MODE_ENCRYPTION_NO_MITM;
00173                             break;
00174                         case 3:
00175                             resolvedSecurityMode = Gap::SECURITY_MODE_ENCRYPTION_WITH_MITM;
00176                             break;
00177                     }
00178                     break;
00179                 case 2:
00180                     switch (level) {
00181                         case 1:
00182                             resolvedSecurityMode = Gap::SECURITY_MODE_SIGNED_NO_MITM;
00183                             break;
00184                         case 2:
00185                             resolvedSecurityMode = Gap::SECURITY_MODE_SIGNED_WITH_MITM;
00186                             break;
00187                     }
00188                     break;
00189             }
00190 
00191             nRF51Gap::getInstance().processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode);
00192             break;
00193         }
00194         case DM_EVT_DEVICE_CONTEXT_STORED:
00195             nRF51Gap::getInstance().processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle);
00196             break;
00197         default:
00198             break;
00199     }
00200 
00201     return NRF_SUCCESS;
00202 }