/**@brief Function for handling the Connection Security Update event received from the BLE * stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sec_update(ble_gap_evt_conn_sec_update_t * p_sec_update) { uint8_t security_mode = p_sec_update->conn_sec.sec_mode.sm; uint8_t security_level = p_sec_update->conn_sec.sec_mode.lv; if (((security_mode == 1) && (security_level > 1)) || ((security_mode == 2) && (security_level != 0))) { ENCRYPTION_STATUS_SET(); uint32_t err_code = master_sys_attr_set(&m_master); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } else { m_sys_attr_loaded = true; } if (m_bondmngr_config.evt_handler != NULL) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_ENCRYPTED; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } } }
/**@brief This function handles the connected event received from the BLE stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_connect(ble_evt_t * p_ble_evt) { m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; m_master.bond.master_handle = INVALID_MASTER_HANDLE; m_master.bond.master_addr = p_ble_evt->evt.gap_evt.params.connected.peer_addr; m_master.sys_attr.sys_attr_size = 0; if (p_ble_evt->evt.gap_evt.params.connected.irk_match) { uint8_t irk_idx = p_ble_evt->evt.gap_evt.params.connected.irk_match_idx; if ((irk_idx >= MAX_NUM_MASTER_WHITE_LIST) || (m_whitelist_irk[irk_idx].master_handle >= BLE_BONDMNGR_MAX_BONDED_MASTERS)) { m_bondmngr_config.error_handler(NRF_ERROR_INTERNAL); } else { m_master = m_masters_db[m_whitelist_irk[irk_idx].master_handle]; } } else { int i; for (i = 0; i < m_addr_count; i++) { ble_gap_addr_t * p_cur_addr = m_whitelist_addr[i].p_addr; if (memcmp(p_cur_addr->addr, m_master.bond.master_addr.addr, BLE_GAP_ADDR_LEN) == 0) { m_master = m_masters_db[m_whitelist_addr[i].master_handle]; break; } } } if (m_master.bond.master_handle != INVALID_MASTER_HANDLE) { uint32_t err_code = master_sys_attr_set(&m_master); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } if (m_bondmngr_config.evt_handler != NULL) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_CONN_TO_BONDED_MASTER; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } } }
/**@brief This function handles the authentication status event related to a new master. * * @details This function adds the new master to the database and stores the master's Bonding * Information to flash. It also notifies the application when the new bond is created, * and sets the System Attributes to prepare the stack for connection with the new * master. * * @param[in] p_auth_status New authentication status. * * @return NRF_SUCCESS on success, otherwise an error code. */ static uint32_t on_auth_status_from_new_master(ble_gap_evt_auth_status_t * p_auth_status) { uint32_t err_code; if (m_masters_in_db_count >= BLE_BONDMNGR_MAX_BONDED_MASTERS) { return NRF_ERROR_NO_MEM; } // Update master m_master.bond.auth_status = *p_auth_status; m_master.bond.master_id_info.div = p_auth_status->periph_keys.enc_info.div; m_master.sys_attr.sys_attr_size = 0; // Add new master to database m_master.bond.master_handle = m_masters_in_db_count; m_masters_db[m_masters_in_db_count++] = m_master; update_whitelist(); // Clear System Attributes err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); if (err_code != NRF_SUCCESS) { return err_code; } // Write new master's Bonding Information to flash err_code = bond_info_store(&m_master.bond); if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL)) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } else if (err_code != NRF_SUCCESS) { return err_code; } // Pass event to application if (m_bondmngr_config.evt_handler != NULL) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_NEW_BOND; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } return NRF_SUCCESS; }
/**@brief Function for handling the 'System Attributes Missing' event received from the * SoftDevice. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sys_attr_missing(ble_evt_t * p_ble_evt) { uint32_t err_code; if ( (m_master.bond.master_handle == INVALID_MASTER_HANDLE) || !ENCRYPTION_STATUS_GET() || BONDING_IN_PROGRESS_STATUS_GET() ) { err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); } else { // Current master is valid, use its data. Set the corresponding sys_attr. err_code = master_sys_attr_set(&m_master); if (err_code == NRF_SUCCESS) { // Set System Attributes loaded status variable. m_sys_attr_loaded = true; } } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } }
/**@brief Function for handling the Security Info Request event received from the BLE stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sec_info_request(ble_evt_t * p_ble_evt) { uint32_t err_code; err_code = master_find_in_db(p_ble_evt->evt.gap_evt.params.sec_info_request.div); if (err_code == NRF_SUCCESS) { // Bond information has been found and loaded for security procedures. Reflect this in the // status variable m_bond_loaded = true; // Master found in the list of bonded master. Use the encryption info for this master. err_code = sd_ble_gap_sec_info_reply(m_conn_handle, &m_master.bond.auth_status.periph_keys.enc_info, NULL); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } // Do not set the sys_attr yet, should be set only when sec_update is successful. } else if (err_code == NRF_ERROR_NOT_FOUND) { m_master.bond.master_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request; // New master. err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } // Initialize the sys_attr. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } }
/**@brief This function handles the new authentication status event, received from the * SoftDevice, related to an already bonded master. * * @details This function also writes the updated Bonding Information to flash and notifies the * application. * * @param[in] p_auth_status Updated authentication status. */ static void auth_status_update(ble_gap_evt_auth_status_t * p_auth_status) { if (!auth_status_equal(&m_master.bond.auth_status, p_auth_status)) { uint32_t err_code; // Authentication status changed, update Bonding Information m_master.bond.auth_status = *p_auth_status; m_master.bond.master_id_info.div = p_auth_status->periph_keys.enc_info.div; // Write updated Bonding Information to flash err_code = bond_info_store(&m_master.bond); if ((err_code == NRF_ERROR_NO_MEM) && (m_bondmngr_config.evt_handler != NULL)) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_BOND_FLASH_FULL; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } else if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } // Pass event to the application if (m_bondmngr_config.evt_handler != NULL) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_AUTH_STATUS_UPDATED; evt.master_handle = m_master.bond.master_handle; evt.master_id = m_master.bond.master_id_info.div; m_bondmngr_config.evt_handler(&evt); } } }
/**@brief This function handles the Security Info Request event received from the BLE stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sec_info_request(ble_evt_t * p_ble_evt) { uint32_t err_code; m_master.bond.master_id_info = p_ble_evt->evt.gap_evt.params.sec_info_request; err_code = master_find_in_db(m_master.bond.master_id_info.div); if (err_code == NRF_SUCCESS) { // Master found in the list of bonded master. Use the encryption info for this master. err_code = sd_ble_gap_sec_info_reply(m_conn_handle, &m_master.bond.auth_status.periph_keys.enc_info, NULL); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } // In addition set the corresponding sys_attr err_code = master_sys_attr_set(&m_master); } else if (err_code == NRF_ERROR_NOT_FOUND) { // New master err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL); if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } // Initialize the sys_attr err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } }
void ble_bondmngr_on_ble_evt(ble_evt_t * p_ble_evt) { if (!m_is_bondmngr_initialized) { m_bondmngr_config.error_handler(NRF_ERROR_INVALID_STATE); } switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: on_connect(p_ble_evt); break; // NOTE: All actions to be taken on the Disconnected event are performed in // ble_bondmngr_bonded_masters_store(). This function must be called from the // Disconnected handler of the application before advertising is restarted (to make // sure the flash blocks are cleared while the radio is inactive). case BLE_GAP_EVT_DISCONNECTED: SECURITY_STATUS_RESET(); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: on_sys_attr_missing(p_ble_evt); break; case BLE_GAP_EVT_AUTH_STATUS: on_auth_status(&p_ble_evt->evt.gap_evt.params.auth_status); break; case BLE_GAP_EVT_SEC_INFO_REQUEST: on_sec_info_request(p_ble_evt); break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: on_sec_param_request(&p_ble_evt->evt.gap_evt.params.sec_params_request); break; case BLE_GAP_EVT_CONN_SEC_UPDATE: on_sec_update(&p_ble_evt->evt.gap_evt.params.conn_sec_update); break; default: break; } }
/**@brief This function handles the 'System Attributes Missing' event received from the * SoftDevice. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sys_attr_missing(ble_evt_t * p_ble_evt) { uint32_t err_code; if (m_master.bond.master_handle == INVALID_MASTER_HANDLE) { err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0); } else { // Current master is valid, use its data. Set the corresponding sys_attr. err_code = master_sys_attr_set(&m_master); } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } }
/**@brief Connection Security Update event handler. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_sec_update(ble_gap_evt_conn_sec_update_t * p_sec_update) { uint8_t security_mode = p_sec_update->conn_sec.sec_mode.sm; uint8_t security_level = p_sec_update->conn_sec.sec_mode.lv; if (((security_mode == 1) && (security_level > 1)) || ((security_mode == 2) && (security_level != 0))) { if (m_bondmngr_config.evt_handler != NULL) { ble_bondmngr_evt_t evt; evt.evt_type = BLE_BONDMNGR_EVT_ENCRYPTED; evt.master_handle = m_master.bond.master_handle; m_bondmngr_config.evt_handler(&evt); } } }
/**@brief Function for handling the Authentication Status event received from the BLE stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_auth_status(ble_gap_evt_auth_status_t * p_auth_status) { if (p_auth_status->auth_status != BLE_GAP_SEC_STATUS_SUCCESS) { return; } // Verify if its pairing and not bonding if (!ENCRYPTION_STATUS_GET()) { return; } if (m_master.bond.master_handle == INVALID_MASTER_HANDLE) { uint32_t err_code = master_find_in_db(p_auth_status->periph_keys.enc_info.div); if (err_code == NRF_SUCCESS) { // Possible DIV Collision indicate error to application, // not storing the new LTK err_code = NRF_ERROR_FORBIDDEN; } else { // Add the new device to data base err_code = on_auth_status_from_new_master(p_auth_status); } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } } else { m_bond_loaded = true; // Receiving a auth status again when already in have existing information! auth_status_update(p_auth_status); } }
/**@brief This function handles the Authentication Status event received from the BLE stack. * * @param[in] p_ble_evt Event received from the BLE stack. */ static void on_auth_status(ble_gap_evt_auth_status_t * p_auth_status) { if (p_auth_status->auth_status != BLE_GAP_SEC_STATUS_SUCCESS) { return; } if (m_master.bond.master_handle == INVALID_MASTER_HANDLE) { uint32_t err_code = master_find_in_db(p_auth_status->periph_keys.enc_info.div); switch (err_code) { case NRF_SUCCESS: // Master found in the list of bonded masters. Set the corresponding sys_attr. err_code = master_sys_attr_set(&m_master); break; case NRF_ERROR_NOT_FOUND: // Master not found, add new master err_code = on_auth_status_from_new_master(p_auth_status); break; default: break; } if (err_code != NRF_SUCCESS) { m_bondmngr_config.error_handler(err_code); } } else { auth_status_update(p_auth_status); } }