Files
VivaMyo-firmware-test/project/ble_peripheral/ble_app_vivaMayo/ble/ble_security.c
2026-04-08 16:59:20 +09:00

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 */