패스키 최초 1회 변경 가능 제한

This commit is contained in:
2026-06-16 11:28:28 +09:00
parent cfae61eff4
commit a506641776
5 changed files with 148 additions and 4 deletions
+30
View File
@@ -19,11 +19,13 @@
#define APP_NVS_KEY_HW_NO "hw" #define APP_NVS_KEY_HW_NO "hw"
#define APP_NVS_KEY_SERIAL_NO "serial" #define APP_NVS_KEY_SERIAL_NO "serial"
#define APP_NVS_KEY_PASSKEY "passkey" #define APP_NVS_KEY_PASSKEY "passkey"
#define APP_NVS_KEY_PASSKEY_CHANGED "passkey_changed" /* 패스키 1회 변경 완료 플래그 */
#define APP_NVS_FULL_KEY_PIEZO "vesiscan/piezo" #define APP_NVS_FULL_KEY_PIEZO "vesiscan/piezo"
#define APP_NVS_FULL_KEY_HW_NO "vesiscan/hw" #define APP_NVS_FULL_KEY_HW_NO "vesiscan/hw"
#define APP_NVS_FULL_KEY_SERIAL_NO "vesiscan/serial" #define APP_NVS_FULL_KEY_SERIAL_NO "vesiscan/serial"
#define APP_NVS_FULL_KEY_PASSKEY "vesiscan/passkey" #define APP_NVS_FULL_KEY_PASSKEY "vesiscan/passkey"
#define APP_NVS_FULL_KEY_PASSKEY_CHANGED "vesiscan/passkey_changed" /* 값 0은 변경 가능, 값 1은 변경 차단 */
static piezo_config_t *m_piezo_cfg; static piezo_config_t *m_piezo_cfg;
static app_nvs_piezo_validate_fn m_piezo_validate; static app_nvs_piezo_validate_fn m_piezo_validate;
@@ -122,6 +124,18 @@ static int app_nvs_settings_set(const char *name, size_t len,
return read_exact(read_cb, cb_arg, m_static_passkey, PASSKEY_LENGTH, APP_NVS_KEY_PASSKEY); return read_exact(read_cb, cb_arg, m_static_passkey, PASSKEY_LENGTH, APP_NVS_KEY_PASSKEY);
} }
if (settings_name_steq(name, APP_NVS_KEY_PASSKEY_CHANGED, &next) && (next == NULL))
{
/* 저장된 변경 완료 플래그 복원 */
if (len != sizeof(m_passkey_changed))
{
DBG_ERR("[NVS] passkey_changed size mismatch (%u)\r\n", (uint32_t)len);
return -EINVAL;
}
return read_exact(read_cb, cb_arg, &m_passkey_changed, sizeof(m_passkey_changed), APP_NVS_KEY_PASSKEY_CHANGED);
}
return -ENOENT; return -ENOENT;
} }
@@ -220,3 +234,19 @@ int app_nvs_save_passkey(const char *passkey)
return 0; return 0;
#endif #endif
} }
int app_nvs_save_passkey_changed(uint8_t changed)
{
#if IS_ENABLED(CONFIG_SETTINGS)
/* 패스키 변경 성공 후 재부팅해도 재변경 차단 */
int err = settings_save_one(APP_NVS_FULL_KEY_PASSKEY_CHANGED, &changed, sizeof(changed));
if (err)
{
DBG_ERR("[NVS] passkey_changed save failed err=%d\r\n", err);
}
return err;
#else
ARG_UNUSED(changed);
return 0;
#endif
}
+1
View File
@@ -20,5 +20,6 @@ int app_nvs_save_piezo(const piezo_config_t *cfg);
int app_nvs_save_hw_no(const char *hw_no); int app_nvs_save_hw_no(const char *hw_no);
int app_nvs_save_serial_no(const char *serial_no); int app_nvs_save_serial_no(const char *serial_no);
int app_nvs_save_passkey(const char *passkey); int app_nvs_save_passkey(const char *passkey);
int app_nvs_save_passkey_changed(uint8_t changed);
#endif /* APP_NVS_H__ */ #endif /* APP_NVS_H__ */
+5 -1
View File
@@ -67,10 +67,11 @@ uint8_t m_reset_status = 1; /* 리셋 상태 코드 */
char SERIAL_NO[SERIAL_NO_BUF_SIZE]; /* 시리얼 번호 */ char SERIAL_NO[SERIAL_NO_BUF_SIZE]; /* 시리얼 번호 */
char HW_NO[HW_NO_BUF_SIZE]; /* 하드웨어 번호 */ char HW_NO[HW_NO_BUF_SIZE]; /* 하드웨어 번호 */
char m_static_passkey[PASSKEY_BUF_SIZE]; /* BLE 정적 패스키 */ char m_static_passkey[PASSKEY_BUF_SIZE]; /* BLE 정적 패스키 */
uint8_t m_passkey_changed; /* 패스키 변경은 출고 후 1회만 허용 */
static uint16_t cnt_s; /* 전원 버튼 폴링 카운터 (5ms 단위) */ static uint16_t cnt_s; /* 전원 버튼 폴링 카운터 (5ms 단위) */
static bool device_on = false; /* 디바이스 전원 상태 (래치 완료 여부) */ static bool device_on = false; /* 디바이스 전원 상태 (래치 완료 여부) */
static bool boot_btn_released = false; /* 부팅 후 버튼 놓았는지 여부 */ static bool boot_btn_released = false; /* 부팅 후 버튼 놓았는지 여부 */
static bool power_btn_suspended; /* 측정 중 전원 버튼 상태머신 일시 정지 */ static bool power_btn_suspended; /* 측정 중 전원 버튼 상태머신 일시 정지 */
/* /*
@@ -310,6 +311,9 @@ static void load_default_config(void)
memset(m_static_passkey, 0, sizeof(m_static_passkey)); memset(m_static_passkey, 0, sizeof(m_static_passkey));
memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len); memcpy(m_static_passkey, DEFAULT_PASSKEY, passkey_len);
/* NVS 로드 전 기본값은 변경 가능 상태 */
m_passkey_changed = 0U;
/* 기본 상태값 */ /* 기본 상태값 */
m_reset_status = 1; m_reset_status = 1;
bond_data_delete = true; bond_data_delete = true;
+1
View File
@@ -74,6 +74,7 @@ extern volatile bool processing;
extern char SERIAL_NO[SERIAL_NO_BUF_SIZE]; extern char SERIAL_NO[SERIAL_NO_BUF_SIZE];
extern char HW_NO[HW_NO_BUF_SIZE]; extern char HW_NO[HW_NO_BUF_SIZE];
extern char m_static_passkey[PASSKEY_BUF_SIZE]; extern char m_static_passkey[PASSKEY_BUF_SIZE];
extern uint8_t m_passkey_changed;
extern bool bond_data_delete; extern bool bond_data_delete;
extern uint32_t m_life_cycle; extern uint32_t m_life_cycle;
extern uint8_t m_reset_status; extern uint8_t m_reset_status;
+111 -3
View File
@@ -9,6 +9,11 @@
******************************************************************************/ ******************************************************************************/
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/sys/util.h> #include <zephyr/sys/util.h>
#include <zephyr/sys/reboot.h>
#if IS_ENABLED(CONFIG_BT_SMP)
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#endif
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
@@ -131,6 +136,12 @@ int piezo_config_init(void)
return 0; return 0;
} }
static void reboot_after_response(void)
{
k_msleep(100);
sys_reboot(SYS_REBOOT_COLD);
}
/*============================================================================== /*==============================================================================
* CRC16 (CRC-CCITT, Nordic SDK ) * CRC16 (CRC-CCITT, Nordic SDK )
*============================================================================*/ *============================================================================*/
@@ -697,6 +708,77 @@ static int cmd_msn(const uint8_t *data, uint8_t data_len)
return 1; return 1;
} }
static int cmd_msq(const uint8_t *data, uint8_t data_len)
{
ARG_UNUSED(data);
ARG_UNUSED(data_len);
int err = send_response_u16("rsq:", 0x0000);
if (err)
{
DBG_ERR("[CMD] msq tx failed err=%d\r\n", err);
}
DBG_PRINTF("[CMD] msq -> power off\r\n");
sleep_mode_enter();
return 1;
}
static int cmd_mss(const uint8_t *data, uint8_t data_len)
{
ARG_UNUSED(data);
ARG_UNUSED(data_len);
int err = send_response_u16("rss:", 0x0000);
if (err)
{
DBG_ERR("[CMD] mss tx failed err=%d\r\n", err);
}
DBG_PRINTF("[CMD] mss -> reboot\r\n");
reboot_after_response();
return 1;
}
static int cmd_msr(const uint8_t *data, uint8_t data_len)
{
uint16_t status = 0x0000;
ARG_UNUSED(data);
ARG_UNUSED(data_len);
#if IS_ENABLED(CONFIG_BT_SMP)
int err = bt_unpair(BT_ID_DEFAULT, NULL);
if (err)
{
status = (uint16_t)(-err);
DBG_ERR("[CMD] msr bt_unpair failed err=%d\r\n", err);
}
else
{
bond_data_delete = true;
DBG_PRINTF("[CMD] msr bond data deleted\r\n");
}
#else
bond_data_delete = true;
DBG_PRINTF("[CMD] msr bond delete skipped (BT_SMP disabled)\r\n");
#endif
int tx_err = send_response_u16("rsr:", status);
if (tx_err)
{
DBG_ERR("[CMD] msr tx failed err=%d\r\n", tx_err);
}
if (status == 0x0000)
{
DBG_PRINTF("[CMD] msr -> reboot\r\n");
reboot_after_response();
}
return 1;
}
/* msp? → IMU 1회 측정 → rsp: + accel XYZ + gyro XYZ (각 int16 빅엔디안) */ /* msp? → IMU 1회 측정 → rsp: + accel XYZ + gyro XYZ (각 int16 빅엔디안) */
static int cmd_msp(const uint8_t *data, uint8_t data_len) static int cmd_msp(const uint8_t *data, uint8_t data_len)
{ {
@@ -1328,15 +1410,38 @@ static int cmd_mpz(const uint8_t *data, uint8_t data_len)
return 1; return 1;
} }
memset(m_static_passkey, 0, sizeof(m_static_passkey)); if (m_passkey_changed != 0U)
memcpy(m_static_passkey, data, PASSKEY_LENGTH); {
int err = app_nvs_save_passkey(m_static_passkey); /* 패스키가 변경된 경우 다시 바꿀 수 없음(FFFF 반환) */
send_response_u16("rpz:", 0xFFFF);
DBG_PRINTF("[CMD] mpz: passkey already changed\r\n");
return 1;
}
/* NVS 저장이 모두 성공한 뒤 RAM 값 확정 */
char new_passkey[PASSKEY_BUF_SIZE];
memset(new_passkey, 0, sizeof(new_passkey));
memcpy(new_passkey, data, PASSKEY_LENGTH);
int err = app_nvs_save_passkey(new_passkey);
if (err) if (err)
{ {
send_response_u16("rpz:", 0xFFFD); send_response_u16("rpz:", 0xFFFD);
return 1; return 1;
} }
/* 변경 완료 플래그 세트 : 다음 mpz? 명령 차단 */
err = app_nvs_save_passkey_changed(1U);
if (err)
{
send_response_u16("rpz:", 0xFFFD);
return 1;
}
memset(m_static_passkey, 0, sizeof(m_static_passkey));
memcpy(m_static_passkey, new_passkey, PASSKEY_LENGTH);
m_passkey_changed = 1U;
send_response_ascii("rpz:", m_static_passkey, PASSKEY_LENGTH); send_response_ascii("rpz:", m_static_passkey, PASSKEY_LENGTH);
DBG_PRINTF("[CMD] mpz updated\r\n"); DBG_PRINTF("[CMD] mpz updated\r\n");
return 1; return 1;
@@ -1396,6 +1501,9 @@ typedef struct
static const cmd_entry_t cmd_table[] = static const cmd_entry_t cmd_table[] =
{ {
{ "msq?", cmd_msq },
{ "mss?", cmd_mss },
{ "msr?", cmd_msr },
{ "msn?", cmd_msn }, { "msn?", cmd_msn },
{ "mls?", cmd_mls }, { "mls?", cmd_mls },
{ "msp?", cmd_msp }, { "msp?", cmd_msp },