200 lines
6.5 KiB
C
200 lines
6.5 KiB
C
/*******************************************************************************
|
|
* @file ble_security.c
|
|
* @brief BLE Security - Peer Manager, LESC, Bonding
|
|
* @author Charles KWON <charleskwon@medithings.co.kr>
|
|
* @date 2025-01-30
|
|
* @copyright (c) 2025 Medithings Inc. All rights reserved.
|
|
*
|
|
* @details Peer Manager initialization and security event handling.
|
|
******************************************************************************/
|
|
|
|
#include "sdk_config.h"
|
|
#include "ble_security.h"
|
|
|
|
#if FEATURE_SECURE_CONNECTION
|
|
|
|
#include "ble_core.h"
|
|
#include "ble_data_tx.h"
|
|
#include "power_ctrl.h"
|
|
#include "device_config.h"
|
|
|
|
#include "peer_manager.h"
|
|
#include "peer_manager_handler.h"
|
|
#include "nrf_ble_lesc.h"
|
|
#include "ble_conn_state.h"
|
|
#include "app_error.h"
|
|
#include "debug_print.h"
|
|
#include "battery_saadc.h"
|
|
#include "ble_quick_security.h"
|
|
#include <string.h>
|
|
|
|
/*==============================================================================
|
|
* GLOBAL VARIABLES
|
|
*============================================================================*/
|
|
|
|
bool erase_bonds = false;
|
|
|
|
/*==============================================================================
|
|
* PRIVATE VARIABLES
|
|
*============================================================================*/
|
|
|
|
static pm_peer_id_t m_peer_to_be_deleted = PM_PEER_ID_INVALID;
|
|
static uint8_t c_addr[6];
|
|
|
|
/*==============================================================================
|
|
* PEER MANAGER EVENT HANDLER
|
|
*============================================================================*/
|
|
|
|
static void pm_evt_handler(pm_evt_t const * p_evt)
|
|
{
|
|
pm_peer_data_bonding_t peer_bonding_data;
|
|
uint32_t return_code;
|
|
ret_code_t err_code;
|
|
|
|
/* Standard Peer Manager handlers */
|
|
pm_handler_on_pm_evt(p_evt);
|
|
pm_handler_disconnect_on_sec_failure(p_evt);
|
|
pm_handler_flash_clean(p_evt);
|
|
|
|
/* Security module (automatic mode handling) */
|
|
ble_security_quick_pm_handler(p_evt);
|
|
|
|
/* Application-specific event handling */
|
|
switch (p_evt->evt_id)
|
|
{
|
|
case PM_EVT_CONN_SEC_SUCCEEDED:
|
|
{
|
|
pm_conn_sec_status_t conn_sec_status;
|
|
err_code = pm_conn_sec_status_get(p_evt->conn_handle, &conn_sec_status);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
/* Accept if: MITM protected OR dev mode (no security) */
|
|
if (conn_sec_status.mitm_protected || BLE_DEV_MODE)
|
|
{
|
|
DBG_PRINTF("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);
|
|
|
|
/* Start battery monitoring after secure connection */
|
|
ble_connection_st = 1;
|
|
battery_timer_start();
|
|
}
|
|
else
|
|
{
|
|
/* Security insufficient - disconnect (production mode) */
|
|
DBG_PRINTF("Link security FAILED\r\n");
|
|
err_code = pm_peer_id_get(m_conn_handle, &m_peer_to_be_deleted);
|
|
APP_ERROR_CHECK(err_code);
|
|
err_code = sd_ble_gap_disconnect(m_conn_handle,
|
|
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PM_EVT_CONN_SEC_FAILED:
|
|
{
|
|
DBG_PRINTF("Security failed: peer_id=%d, error=%d\r\n",
|
|
p_evt->peer_id,
|
|
p_evt->params.conn_sec_failed.error);
|
|
|
|
/* Auto-retry if key missing (supports rebonding) */
|
|
if (p_evt->params.conn_sec_failed.error == PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING)
|
|
{
|
|
err_code = pm_conn_secure(p_evt->conn_handle, true);
|
|
if (err_code != NRF_ERROR_INVALID_STATE)
|
|
{
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case PM_EVT_PEERS_DELETE_SUCCEEDED:
|
|
/* Restart advertising after bond deletion */
|
|
advertising_start(false);
|
|
break;
|
|
|
|
case PM_EVT_CONN_SEC_CONFIG_REQ:
|
|
{
|
|
/* Allow repairing for rebonding support */
|
|
pm_conn_sec_config_t conn_sec_config = {
|
|
.allow_repairing = true
|
|
};
|
|
pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config);
|
|
}
|
|
break;
|
|
|
|
case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
|
|
{
|
|
/* Store peer address for tracking */
|
|
return_code = pm_peer_data_bonding_load(p_evt->peer_id, &peer_bonding_data);
|
|
|
|
if (return_code == NRF_SUCCESS)
|
|
{
|
|
DBG_PRINTF("Peer updated: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[5],
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[4],
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[3],
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[2],
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[1],
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr[0]);
|
|
|
|
memcpy(c_addr,
|
|
peer_bonding_data.peer_ble_id.id_addr_info.addr,
|
|
sizeof(c_addr));
|
|
|
|
DBG_PRINTF("Stored c_addr[3]: %02x\r\n", c_addr[3]);
|
|
m_reset_status = 10;
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINTF("Failed to load peer data: error=%d\r\n", return_code);
|
|
m_reset_status = 10;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*==============================================================================
|
|
* PUBLIC FUNCTIONS
|
|
*============================================================================*/
|
|
|
|
void peer_manager_init(void)
|
|
{
|
|
ret_code_t err_code;
|
|
|
|
/* Security mode auto-configuration */
|
|
ble_security_quick_init(BLE_DEV_MODE);
|
|
|
|
/* Register PM event handler */
|
|
err_code = pm_register(pm_evt_handler);
|
|
APP_ERROR_CHECK(err_code);
|
|
|
|
DBG_PRINTF("BLE Security initialized (mode=%d)\r\n", BLE_DEV_MODE);
|
|
}
|
|
|
|
void delete_bonds(void)
|
|
{
|
|
ret_code_t err_code;
|
|
|
|
DBG_PRINTF("Erase bonds!\r\n");
|
|
|
|
err_code = pm_peers_delete();
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
|
|
void security_idle_state_handle(void)
|
|
{
|
|
ret_code_t err_code;
|
|
err_code = nrf_ble_lesc_request_handler();
|
|
APP_ERROR_CHECK(err_code);
|
|
}
|
|
|
|
#endif /* FEATURE_SECURE_CONNECTION */
|