Allowlist - pairing window open/close 추가

- 신규 페어링 제한 및 인증 실패 제한- Allowlist: 등록된 central만 페어링 기본 허용- 출고 직후 / bond 없는 상태: pairing window open  → central이 연결 후 처음 페어링 성공  → 본딩 정보 저장 : 페어링된 central 등록, pairing window close  → 이후 평상시에는 등록된 central만 연결 허용- 재등록/초기화  → 전원 버튼 15초 롱프레스로 본딩 정보 삭제  → 10분간 pairing window open  → 10분 내 페어링 완료 시 본딩 정보 저장 : central 등록, pairing window close  → 10분 내 페어링 미완료 시 : pairing window close
This commit is contained in:
2026-08-04 16:18:01 +09:00
parent fd79faa39d
commit 7aeb7384cd
4 changed files with 125 additions and 4 deletions
+120 -4
View File
@@ -15,6 +15,7 @@
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
#include <hal/nrf_power.h>
#if IS_ENABLED(CONFIG_SETTINGS)
#include <zephyr/settings/settings.h>
#endif
@@ -41,7 +42,14 @@ static uint16_t current_notify_mtu = 23U;
#if IS_ENABLED(CONFIG_BT_SMP)
#define BLE_REQUIRED_SECURITY_LEVEL BT_SECURITY_L4
#define PAIRING_WINDOW_TIMEOUT_MS (10 * 60 * 1000)
#define PAIRING_WINDOW_GPREGRET_REG 0U
#define PAIRING_WINDOW_GPREGRET_MAGIC 0xB0U
static uint32_t pairing_passkey = BT_PASSKEY_RAND;
static bool bond_peer_exists;
static bool pairing_window_open;
static bool pairing_window_limited;
static struct k_work_delayable pairing_window_timeout_work;
#endif
/*
@@ -132,6 +140,84 @@ static void ble_log_local_identity(void)
#if IS_ENABLED(CONFIG_BT_SMP)
/* NUS 접근 전 보안 level 확인 */
static bool ble_conn_is_secure(const struct bt_conn *conn);
static void pairing_window_close(void)
{
pairing_window_open = false;
pairing_window_limited = false;
k_work_cancel_delayable(&pairing_window_timeout_work);
DBG_CORE("[BLE] Pairing window closed\r\n");
}
static void pairing_window_open_set(bool limited)
{
pairing_window_open = true;
pairing_window_limited = limited;
if (limited)
{
k_work_schedule(&pairing_window_timeout_work, K_MSEC(PAIRING_WINDOW_TIMEOUT_MS));
DBG_CORE("[BLE] Pairing window opened (10min)\r\n");
}
else
{
k_work_cancel_delayable(&pairing_window_timeout_work);
DBG_CORE("[BLE] Pairing window opened (factory)\r\n");
}
}
static void pairing_window_timeout_handler(struct k_work *work)
{
ARG_UNUSED(work);
if (pairing_window_limited)
{
pairing_window_close();
if (current_conn != NULL && !ble_conn_is_secure(current_conn))
{
DBG_ERR("[BLE] Pairing window timeout -> disconnect unsecured peer\r\n");
(void)bt_conn_disconnect(current_conn, BT_HCI_ERR_AUTH_FAIL);
}
}
}
static void bond_check_cb(const struct bt_bond_info *info, void *user_data)
{
bool *found = (bool *)user_data;
ARG_UNUSED(info);
*found = true;
}
static bool ble_consume_pairing_window_reset_request(void)
{
#if NRF_POWER_HAS_GPREGRET
if (nrf_power_gpregret_get(NRF_POWER, PAIRING_WINDOW_GPREGRET_REG) == PAIRING_WINDOW_GPREGRET_MAGIC)
{
nrf_power_gpregret_set(NRF_POWER, PAIRING_WINDOW_GPREGRET_REG, 0U);
return true;
}
#endif
return false;
}
static void ble_pairing_window_init_from_bonds(void)
{
bool reset_request = ble_consume_pairing_window_reset_request();
bond_peer_exists = false;
bt_foreach_bond(BT_ID_DEFAULT, bond_check_cb, &bond_peer_exists);
DBG_CORE("[BLE] Bond peer exists=%u reset_window=%u\r\n", bond_peer_exists ? 1U : 0U, reset_request ? 1U : 0U);
if (bond_peer_exists)
{
pairing_window_close();
}
else
{
pairing_window_open_set(reset_request);
}
}
static bool ble_conn_is_secure(const struct bt_conn *conn)
{
return (conn != NULL) && (bt_conn_get_security(conn) >= BLE_REQUIRED_SECURITY_LEVEL);
@@ -190,8 +276,16 @@ static int ble_security_configure(void)
/* Just Works/passkey pairing 요청 자동 승인 */
static void auth_pairing_confirm(struct bt_conn *conn)
{
int err = bt_conn_auth_pairing_confirm(conn);
int err;
if (!pairing_window_open)
{
DBG_ERR("[BLE] Pairing rejected: window closed\r\n");
(void)bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
return;
}
err = bt_conn_auth_pairing_confirm(conn);
if (err)
{
DBG_ERR("[BLE] Pairing confirm failed err=%d\r\n", err);
@@ -214,6 +308,13 @@ static uint32_t auth_app_passkey(struct bt_conn *conn)
{
unsigned int passkey;
if (!pairing_window_open)
{
DBG_ERR("[BLE] Passkey rejected: pairing window closed\r\n");
(void)bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
return pairing_passkey;
}
ARG_UNUSED(conn);
if (ble_passkey_to_uint(m_static_passkey, &passkey) == 0)
@@ -241,6 +342,11 @@ static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
{
ARG_UNUSED(conn);
DBG_CORE("[BLE] Pairing complete bonded=%u\r\n", bonded ? 1U : 0U);
if (bonded)
{
bond_peer_exists = true;
pairing_window_close();
}
}
/* pairing 실패 시 연결 종료 */
@@ -546,11 +652,10 @@ static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t l
/* BLE security level 변경 결과 확인 */
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
ARG_UNUSED(conn);
if (err)
{
DBG_ERR("[BLE] Security failed level=%u err=%u\r\n", level, err);
DBG_ERR("[BLE] Security failed level=%u err=%u window=%u\r\n", level, err, pairing_window_open ? 1U : 0U);
(void)bt_conn_disconnect(conn, BT_HCI_ERR_AUTH_FAIL);
return;
}
@@ -624,6 +729,9 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
k_work_init(&adv_restart_work, adv_restart_handler);
k_work_init_delayable(&adv_timeout_work, adv_timeout_handler);
k_work_init_delayable(&conn_param_update_work, conn_param_update_handler);
#if IS_ENABLED(CONFIG_BT_SMP)
k_work_init_delayable(&pairing_window_timeout_work, pairing_window_timeout_handler);
#endif
ble_tx_power_init();
// BLE stack 활성화
err = bt_enable(NULL);
@@ -653,6 +761,7 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
{
return err;
}
ble_pairing_window_init_from_bonds();
#endif
// NUS service 초기화
@@ -855,6 +964,13 @@ int ble_data_send(const uint8_t *data, uint16_t len)
}
/* BLE 연결 상태 */
void ble_pairing_window_mark_reset_open(void)
{
#if IS_ENABLED(CONFIG_BT_SMP) && NRF_POWER_HAS_GPREGRET
nrf_power_gpregret_set(NRF_POWER, PAIRING_WINDOW_GPREGRET_REG, PAIRING_WINDOW_GPREGRET_MAGIC);
#endif
}
bool ble_is_connected(void)
{
return (current_conn != NULL);
+1
View File
@@ -36,5 +36,6 @@ int ble_dfu_advertising_enable(void);
bool ble_dfu_advertising_is_enabled(void);
bool ble_is_connected(void);
int ble_disconnect_active(void);
void ble_pairing_window_mark_reset_open(void);
#endif /* BLE_SERVICE_H__ */