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:
+120
-4
@@ -15,6 +15,7 @@
|
|||||||
#include <zephyr/bluetooth/conn.h>
|
#include <zephyr/bluetooth/conn.h>
|
||||||
#include <zephyr/bluetooth/uuid.h>
|
#include <zephyr/bluetooth/uuid.h>
|
||||||
#include <zephyr/bluetooth/gatt.h>
|
#include <zephyr/bluetooth/gatt.h>
|
||||||
|
#include <hal/nrf_power.h>
|
||||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||||
#include <zephyr/settings/settings.h>
|
#include <zephyr/settings/settings.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -41,7 +42,14 @@ static uint16_t current_notify_mtu = 23U;
|
|||||||
|
|
||||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||||
#define BLE_REQUIRED_SECURITY_LEVEL BT_SECURITY_L4
|
#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 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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -132,6 +140,84 @@ static void ble_log_local_identity(void)
|
|||||||
|
|
||||||
#if IS_ENABLED(CONFIG_BT_SMP)
|
#if IS_ENABLED(CONFIG_BT_SMP)
|
||||||
/* NUS 접근 전 보안 level 확인 */
|
/* 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)
|
static bool ble_conn_is_secure(const struct bt_conn *conn)
|
||||||
{
|
{
|
||||||
return (conn != NULL) && (bt_conn_get_security(conn) >= BLE_REQUIRED_SECURITY_LEVEL);
|
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 요청 자동 승인 */
|
/* Just Works/passkey pairing 요청 자동 승인 */
|
||||||
static void auth_pairing_confirm(struct bt_conn *conn)
|
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)
|
if (err)
|
||||||
{
|
{
|
||||||
DBG_ERR("[BLE] Pairing confirm failed err=%d\r\n", 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;
|
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);
|
ARG_UNUSED(conn);
|
||||||
|
|
||||||
if (ble_passkey_to_uint(m_static_passkey, &passkey) == 0)
|
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);
|
ARG_UNUSED(conn);
|
||||||
DBG_CORE("[BLE] Pairing complete bonded=%u\r\n", bonded ? 1U : 0U);
|
DBG_CORE("[BLE] Pairing complete bonded=%u\r\n", bonded ? 1U : 0U);
|
||||||
|
if (bonded)
|
||||||
|
{
|
||||||
|
bond_peer_exists = true;
|
||||||
|
pairing_window_close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pairing 실패 시 연결 종료 */
|
/* pairing 실패 시 연결 종료 */
|
||||||
@@ -546,11 +652,10 @@ static void le_param_updated(struct bt_conn *conn, uint16_t interval, uint16_t l
|
|||||||
/* BLE security level 변경 결과 확인 */
|
/* BLE security level 변경 결과 확인 */
|
||||||
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
|
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(conn);
|
|
||||||
|
|
||||||
if (err)
|
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;
|
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(&adv_restart_work, adv_restart_handler);
|
||||||
k_work_init_delayable(&adv_timeout_work, adv_timeout_handler);
|
k_work_init_delayable(&adv_timeout_work, adv_timeout_handler);
|
||||||
k_work_init_delayable(&conn_param_update_work, conn_param_update_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_tx_power_init();
|
||||||
// BLE stack 활성화
|
// BLE stack 활성화
|
||||||
err = bt_enable(NULL);
|
err = bt_enable(NULL);
|
||||||
@@ -653,6 +761,7 @@ int ble_service_init(ble_data_rx_cb_t rx_cb)
|
|||||||
{
|
{
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
ble_pairing_window_init_from_bonds();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// NUS service 초기화
|
// NUS service 초기화
|
||||||
@@ -855,6 +964,13 @@ int ble_data_send(const uint8_t *data, uint16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* BLE 연결 상태 */
|
/* 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)
|
bool ble_is_connected(void)
|
||||||
{
|
{
|
||||||
return (current_conn != NULL);
|
return (current_conn != NULL);
|
||||||
|
|||||||
@@ -36,5 +36,6 @@ int ble_dfu_advertising_enable(void);
|
|||||||
bool ble_dfu_advertising_is_enabled(void);
|
bool ble_dfu_advertising_is_enabled(void);
|
||||||
bool ble_is_connected(void);
|
bool ble_is_connected(void);
|
||||||
int ble_disconnect_active(void);
|
int ble_disconnect_active(void);
|
||||||
|
void ble_pairing_window_mark_reset_open(void);
|
||||||
|
|
||||||
#endif /* BLE_SERVICE_H__ */
|
#endif /* BLE_SERVICE_H__ */
|
||||||
|
|||||||
@@ -76,10 +76,12 @@ int cmd_msr(const uint8_t *data, uint8_t data_len)
|
|||||||
{
|
{
|
||||||
led_set_state(LED_STATE_BOND_DELETE);
|
led_set_state(LED_STATE_BOND_DELETE);
|
||||||
bond_data_delete = true;
|
bond_data_delete = true;
|
||||||
|
ble_pairing_window_mark_reset_open();
|
||||||
DBG_PRINTF("[CMD] msr bond data deleted\r\n");
|
DBG_PRINTF("[CMD] msr bond data deleted\r\n");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
bond_data_delete = true;
|
bond_data_delete = true;
|
||||||
|
ble_pairing_window_mark_reset_open();
|
||||||
DBG_PRINTF("[CMD] msr bond delete skipped (BT_SMP disabled)\r\n");
|
DBG_PRINTF("[CMD] msr bond delete skipped (BT_SMP disabled)\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -88,10 +88,12 @@ static void bond_reset_work_handler(struct k_work *work)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
bond_data_delete = true;
|
bond_data_delete = true;
|
||||||
|
ble_pairing_window_mark_reset_open();
|
||||||
DBG_PRINTF("[BTN] BLE bond data deleted\r\n");
|
DBG_PRINTF("[BTN] BLE bond data deleted\r\n");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
bond_data_delete = true;
|
bond_data_delete = true;
|
||||||
|
ble_pairing_window_mark_reset_open();
|
||||||
DBG_PRINTF("[BTN] BLE bond delete skipped (BT_SMP disabled)\r\n");
|
DBG_PRINTF("[BTN] BLE bond delete skipped (BT_SMP disabled)\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user