/**@brief Function for the Peer Manager initialization. */ static void peer_manager_init(void) { ble_gap_sec_params_t sec_param; ret_code_t err_code; err_code = pm_init(); APP_ERROR_CHECK(err_code); memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. sec_param.bond = SEC_PARAM_BOND; sec_param.mitm = SEC_PARAM_MITM; sec_param.lesc = SEC_PARAM_LESC; sec_param.keypress = SEC_PARAM_KEYPRESS; sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; sec_param.oob = SEC_PARAM_OOB; sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; sec_param.kdist_own.enc = 1; sec_param.kdist_own.id = 1; sec_param.kdist_peer.enc = 1; sec_param.kdist_peer.id = 1; err_code = pm_sec_params_set(&sec_param); APP_ERROR_CHECK(err_code); err_code = pm_register(pm_evt_handler); APP_ERROR_CHECK(err_code); }
ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode) { // use default and updated parameters as starting point // and modify structure based on security mode. ret_code_t rc; switch (securityMode) { case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK: /**< Require no protection, open link. */ securityParameters.bond = false; securityParameters.mitm = false; securityParameters.kdist_own.enc = 0; break; case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM: /**< Require encryption, but no MITM protection. */ securityParameters.bond = true; securityParameters.mitm = false; securityParameters.kdist_own.enc = 1; break; // not yet implemented security modes case SecurityManager::SECURITY_MODE_NO_ACCESS: case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM: /**< Require encryption and MITM protection. */ case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM: /**< Require signing or encryption, but no MITM protection. */ case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM: /**< Require signing or encryption, and MITM protection. */ default: return BLE_ERROR_NOT_IMPLEMENTED; } // update security settings for given connection rc = pm_sec_params_set(&securityParameters); if (rc == NRF_SUCCESS) { rc = pm_conn_secure(connectionHandle, false); } switch (rc) { case NRF_SUCCESS: initialized = true; return BLE_ERROR_NONE; case NRF_ERROR_INVALID_STATE: return BLE_ERROR_INVALID_STATE; case NRF_ERROR_INVALID_PARAM: return BLE_ERROR_INVALID_PARAM; default: return BLE_ERROR_UNSPECIFIED; } }
/**@brief Function for the Peer Manager initialization. * * @param[in] erase_bonds Indicates whether bonding information should be cleared from * persistent storage during initialization of the Peer Manager. */ static void peer_manager_init(bool erase_bonds) { ble_gap_sec_params_t sec_params; ret_code_t err_code; err_code = pm_init(); APP_ERROR_CHECK(err_code); if (erase_bonds) { (void) pm_peers_delete(); } memset(&sec_params, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. sec_params.bond = SEC_PARAMS_BOND; sec_params.mitm = SEC_PARAMS_MITM; sec_params.lesc = SEC_PARAMS_LESC; sec_params.keypress = SEC_PARAMS_KEYPRESS; sec_params.io_caps = SEC_PARAMS_IO_CAPABILITIES; sec_params.oob = SEC_PARAMS_OOB; sec_params.min_key_size = SEC_PARAMS_MIN_KEY_SIZE; sec_params.max_key_size = SEC_PARAMS_MAX_KEY_SIZE; sec_params.kdist_own.enc = 1; sec_params.kdist_own.id = 1; sec_params.kdist_peer.enc = 1; sec_params.kdist_peer.id = 1; err_code = pm_sec_params_set(&sec_params); APP_ERROR_CHECK(err_code); err_code = pm_register(pm_evt_handler); APP_ERROR_CHECK(err_code); err_code = fds_register(fds_evt_handler); APP_ERROR_CHECK(err_code); ecc_init(); #if LESC_DEBUG_MODE memcpy(m_lesc_sk.sk, m_debug_lesc_sk.sk, BLE_GAP_LESC_P256_SK_LEN); err_code = ecc_p256_public_key_compute((uint8_t *) m_lesc_sk.sk, m_lesc_pk.pk); APP_ERROR_CHECK(err_code); #else err_code = ecc_p256_keypair_gen(m_lesc_sk.sk, m_lesc_pk.pk); APP_ERROR_CHECK(err_code); #endif /* Set the public key */ err_code = pm_lesc_public_key_set(&m_lesc_pk); APP_ERROR_CHECK(err_code); }
/**@brief Function for the Peer Manager initialization. * * @param[in] erase_bonds Indicates whether bonding information should be cleared from * persistent storage during initialization of the Peer Manager. */ static void peer_manager_init(bool erase_bonds) { ble_gap_sec_params_t sec_param; ret_code_t err_code; err_code = pm_init(); APP_ERROR_CHECK(err_code); if (erase_bonds) { pm_peer_delete_all(); } memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. sec_param.bond = SEC_PARAM_BOND; sec_param.mitm = SEC_PARAM_MITM; sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; sec_param.oob = SEC_PARAM_OOB; sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; sec_param.kdist_periph.enc = 1; sec_param.kdist_periph.id = 1; sec_param.kdist_central.enc = 1; sec_param.kdist_central.id = 1; err_code = pm_sec_params_set(&sec_param); APP_ERROR_CHECK(err_code); err_code = pm_register(pm_evt_handler); APP_ERROR_CHECK(err_code); err_code = fds_register(fds_evt_handler); APP_ERROR_CHECK(err_code); }
/**@brief Function for handling Peer Manager events. * * @param[in] p_evt Peer Manager event. */ static void pm_evt_handler(pm_evt_t const * p_evt) { ret_code_t err_code; switch (p_evt->evt_id) { case PM_EVT_BONDED_PEER_CONNECTED: { NRF_LOG_DEBUG("Connected to previously bonded device\r\n"); m_peer_id = p_evt->peer_id; err_code = pm_peer_rank_highest(p_evt->peer_id); if (err_code != NRF_ERROR_BUSY) { APP_ERROR_CHECK(err_code); } }break;//PM_EVT_BONDED_PEER_CONNECTED case PM_EVT_CONN_SEC_START: break;//PM_EVT_CONN_SEC_START case PM_EVT_CONN_SEC_SUCCEEDED: { NRF_LOG_DEBUG("Link secured. Role: %d. conn_handle: %d, Procedure: %d\r\n", ble_conn_state_role(p_evt->conn_handle), p_evt->conn_handle, p_evt->params.conn_sec_succeeded.procedure); err_code = pm_peer_rank_highest(p_evt->peer_id); if (err_code != NRF_ERROR_BUSY) { APP_ERROR_CHECK(err_code); } if (p_evt->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING) { NRF_LOG_DEBUG("New Bond, add the peer to the whitelist if possible\r\n"); NRF_LOG_DEBUG("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d\r\n", m_whitelist_peer_cnt + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT); if (m_whitelist_peer_cnt < BLE_GAP_WHITELIST_ADDR_MAX_COUNT) { //bonded to a new peer, add it to the whitelist. m_whitelist_peers[m_whitelist_peer_cnt++] = m_peer_id; m_is_wl_changed = true; } } }break;//PM_EVT_CONN_SEC_SUCCEEDED case PM_EVT_CONN_SEC_FAILED: { /** In some cases, when securing fails, it can be restarted directly. Sometimes it can * be restarted, but only after changing some Security Parameters. Sometimes, it cannot * be restarted until the link is disconnected and reconnected. Sometimes it is * impossible, to secure the link, or the peer device does not support it. How to * handle this error is highly application dependent. */ switch (p_evt->params.conn_sec_failed.error) { case PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING: // Rebond if one party has lost its keys. err_code = pm_conn_secure(p_evt->conn_handle, true); if (err_code != NRF_ERROR_INVALID_STATE) { APP_ERROR_CHECK(err_code); } break; default: break; } }break;//PM_EVT_CONN_SEC_FAILED case PM_EVT_CONN_SEC_CONFIG_REQ: { // Reject pairing request from an already bonded peer. pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false}; pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); }break;//PM_EVT_CONN_SEC_CONFIG_REQ case PM_EVT_STORAGE_FULL: // Run garbage collection on the flash. err_code = fds_gc(); if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES) { // Retry. } else { APP_ERROR_CHECK(err_code); } break;//PM_EVT_STORAGE_FULL case PM_EVT_ERROR_UNEXPECTED: // A likely fatal error occurred. Assert. APP_ERROR_CHECK(p_evt->params.error_unexpected.error); break;//PM_EVT_ERROR_UNEXPECTED case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: break;//PM_EVT_PEER_DATA_UPDATE_SUCCEEDED case PM_EVT_PEER_DATA_UPDATE_FAILED: APP_ERROR_CHECK(p_evt->params.peer_data_update_failed.error); break;//PM_EVT_PEER_DATA_UPDATE_FAILED case PM_EVT_PEER_DELETE_SUCCEEDED: break;//PM_EVT_PEER_DELETE_SUCCEEDED case PM_EVT_PEER_DELETE_FAILED: APP_ERROR_CHECK(p_evt->params.peer_delete_failed.error); break;//PM_EVT_PEER_DELETE_FAILED case PM_EVT_PEERS_DELETE_SUCCEEDED: break;//PM_EVT_PEERS_DELETE_SUCCEEDED case PM_EVT_PEERS_DELETE_FAILED: APP_ERROR_CHECK(p_evt->params.peers_delete_failed_evt.error); break;//PM_EVT_PEERS_DELETE_FAILED case PM_EVT_LOCAL_DB_CACHE_APPLIED: break;//PM_EVT_LOCAL_DB_CACHE_APPLIED case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED: // The local database has likely changed, send service changed indications. pm_local_database_has_changed(); break;//PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED case PM_EVT_SERVICE_CHANGED_IND_SENT: break;//PM_EVT_SERVICE_CHANGED_IND_SENT case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED: break;//PM_EVT_SERVICE_CHANGED_IND_CONFIRMED default: // No implementation needed. break; } } /**@brief Function for the Peer Manager initialization. * * @param[in] erase_bonds Indicates whether bonding information should be cleared from * persistent storage during initialization of the Peer Manager. */ static void peer_manager_init(bool erase_bonds) { ble_gap_sec_params_t sec_param; ret_code_t err_code; err_code = pm_init(); APP_ERROR_CHECK(err_code); if (erase_bonds) { err_code = pm_peers_delete(); APP_ERROR_CHECK(err_code); } memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); // Security parameters to be used for all security procedures. sec_param.bond = SEC_PARAM_BOND; sec_param.mitm = SEC_PARAM_MITM; sec_param.lesc = SEC_PARAM_LESC; sec_param.keypress = SEC_PARAM_KEYPRESS; sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; sec_param.oob = SEC_PARAM_OOB; sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; sec_param.kdist_own.enc = 1; sec_param.kdist_own.id = 1; sec_param.kdist_peer.enc = 1; sec_param.kdist_peer.id = 1; err_code = pm_sec_params_set(&sec_param); APP_ERROR_CHECK(err_code); err_code = pm_register(pm_evt_handler); APP_ERROR_CHECK(err_code); }
ble_error_t btle_initializeSecurity(bool enableBonding, bool requireMITM, SecurityManager::SecurityIOCapabilities_t iocaps, const SecurityManager::Passkey_t passkey) { /* guard against multiple initializations */ if (initialized) { return BLE_ERROR_NONE; } ret_code_t rc; if (passkey) { ble_opt_t opts; opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey); if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) { switch (rc) { case BLE_ERROR_INVALID_CONN_HANDLE: case NRF_ERROR_INVALID_ADDR: case NRF_ERROR_INVALID_PARAM: default: return BLE_ERROR_INVALID_PARAM; case NRF_ERROR_INVALID_STATE: return BLE_ERROR_INVALID_STATE; case NRF_ERROR_BUSY: return BLE_STACK_BUSY; } } } // update default security parameters with function call parameters securityParameters.bond = enableBonding; securityParameters.mitm = requireMITM; securityParameters.io_caps = iocaps; if (enableBonding) { securityParameters.kdist_own.enc = 1; securityParameters.kdist_own.id = 1; } else { securityParameters.kdist_own.enc = 0; securityParameters.kdist_own.id = 0; } rc = pm_sec_params_set(&securityParameters); if (rc == NRF_SUCCESS) { rc = pm_register(pm_handler); } switch (rc) { case NRF_SUCCESS: initialized = true; return BLE_ERROR_NONE; case NRF_ERROR_INVALID_STATE: return BLE_ERROR_INVALID_STATE; case NRF_ERROR_INVALID_PARAM: return BLE_ERROR_INVALID_PARAM; default: return BLE_ERROR_UNSPECIFIED; } initialized = true; return BLE_ERROR_NONE; }