logic/pin(纯 C):加盐迭代哈希(FNV-1a ×1000 轮 + 每次设置新随机盐,16 位 hex)经
meow_config_* 持久化 pin.enabled/pin.hash/pin.salt;提供 set/verify/change/disable 与
4-8 位纯数字校验;enabled=1 但盐/哈希残缺时 fail-closed;落盘半途失败会还原旧盐,不留
「新盐+旧哈希」的双失效状态。
ui/settings(ACT_SETTINGS):MD3 分组表单(meow_listview 容器圆角卡 + 段头标签)——
阅读方向 RTL/LTR 走 mr_reader_set_direction;启动 PIN 开关与修改(开启/修改均两遍
MEOW_IME_NUM 确认);版本与主题状态行(跟随系统 + 当前明暗,随 app.c 主题 listener
整帧重绘)。控件一律在 on_enter 建(栈顶=ACT_SETTINGS),避免 §6.1 owner 绑到
ACT_LIBRARY 的跨页命中泄漏。
ui/lock(ACT_LOCK):lock_view_should_show() 读 logic/pin;启用时启动先入锁屏,验证前
不绘制任何书库内容;「输入 PIN」按钮弹系统数字键盘(MEOW_IME_NUM),错 PIN 就地提示
重试(无惩罚性锁定),正确则 page_pop 回书库;on_event 消费 SWIPE——左缘返回不能绕过
PIN 或退出 App(meow_view_dispatch_event 先于 app.c 的 on_swipe)。
logic/reader(评审 P1 修复,最小持久化):mr_reader_set_direction 成功切换后 best-effort
写 meow_config("reader.dir","rtl"/"ltr"),写失败只打 WARN 不阻断本次切换;
mr_reader_get_direction 首次调用惰性读一次配置恢复(无配置/非法值 → 默认 RTL),之后
纯内存快路径。宿主测试经 -DMR_READER_TEST_HOOKS 的 mr_reader_test_reset() 模拟重启。
测试/构建:test_pin(85 项,PIN 全分支,含单键半途落盘失败);test_settings_reader_persist
(19 项:默认/落盘/重启恢复/坏值/非法值/只读一次/写失败只告警);可选宿主集成
test_settings_lock_host(真实 SDK view/activity/widget + IME 注入,端到端验证错/对 PIN
解锁与设置页两遍开启;SDK 无源码时 SKIP);run_tests.sh 保持 46/46 并纳入上述测试
(reader.c 的配置/日志依赖由 test/settings_reader_stub.c 存根),build_tuku.sh 加入
logic/pin.c。交叉构建静态 MIPS ELF(zig-mipsel)零警告。
安全口径:PIN 防随手翻看,不是安全边界——TF 卡可拔出直读、配置可改;存储不使用加密库,
锁屏与设置页文案均如实标注该局限。
63 lines
2.9 KiB
C
63 lines
2.9 KiB
C
/* logic/pin.h — APP 启动 PIN(纯 C;宿主可裸测)。
|
||
*
|
||
* 定位(诚实标注):PIN 只挡「随手翻看」——TF 卡可拔出直读,数据目录明文可改,
|
||
* 故不引入加密库、不宣称安全边界。存储口径:加盐迭代哈希(FNV-1a ×1000 轮,
|
||
* 每次设置新随机盐,hex 输出),落在 meow_config_*(App 自有 KV → TF MeowData)。
|
||
* 盐/哈希只做「不知道 PIN 无法直接重算」的轻量门槛,防不了离线暴力或改配置。
|
||
*
|
||
* 配置键(meow_config_*,值均为字符串):
|
||
* pin.enabled = "1"/"0"
|
||
* pin.hash = 16 位 hex(64-bit 摘要)
|
||
* pin.salt = 16 位 hex(每次设置重新生成)
|
||
* enabled=1 但 hash/salt 缺失或格式不合法时一律按「未启用」处理(fail-closed)。
|
||
*
|
||
* 本模块只依赖 include/meow_ui_config.h 的三个声明(get/set/remove/int),不碰 UI;
|
||
* 宿主测试链 test_pin.c 内的 meow_config_* 存根即可,无需 SDK/设备。
|
||
*/
|
||
#ifndef MR_PIN_H
|
||
#define MR_PIN_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define MR_PIN_MIN_LEN 4 /* 允许的最短位数 */
|
||
#define MR_PIN_MAX_LEN 8 /* 允许的最长位数 */
|
||
|
||
/* 返回码(set/change/disable)。verify 用 1/0 表示对/错,不返回错误码。 */
|
||
#define MR_PIN_OK 0 /* 成功 */
|
||
#define MR_PIN_ERR_FORMAT (-1) /* PIN 非法:非 4-8 位纯数字(NULL/空/符号/超长) */
|
||
#define MR_PIN_ERR_STATE (-2) /* 状态不满足:change 时尚未启用 */
|
||
#define MR_PIN_ERR_WRONG (-3) /* change 时原 PIN 校验失败 */
|
||
#define MR_PIN_ERR_STORE (-4) /* meow_config_* 落盘失败(无数据目录/只读/IO) */
|
||
|
||
/* 4-8 位纯 ASCII 数字('0'-'9')→ 1;其余(含 NULL、空串、符号、全角数字)→ 0。 */
|
||
int mr_pin_valid(const char *pin);
|
||
|
||
/* 当前是否启用:1=已启用且 hash/salt 完整合法;0=未启用或配置损坏(fail-closed)。 */
|
||
int mr_pin_enabled(void);
|
||
|
||
/* 设置/重设 PIN(生成新盐 + 迭代哈希并立即落盘)。成功即生效(下次启动进锁屏)。
|
||
* 返回 MR_PIN_OK / MR_PIN_ERR_FORMAT / MR_PIN_ERR_STORE。 */
|
||
int mr_pin_set(const char *pin);
|
||
|
||
/* 校验:1=匹配;0=不匹配/未启用/输入非法(不区分,避免侧信道式提示)。 */
|
||
int mr_pin_verify(const char *pin);
|
||
|
||
/* 修改:先校验 old,再以新盐重设 new。失败时旧 PIN 保持有效(先校验后写盘)。
|
||
* 返回 MR_PIN_OK / MR_PIN_ERR_STATE / MR_PIN_ERR_FORMAT / MR_PIN_ERR_WRONG / MR_PIN_ERR_STORE。 */
|
||
int mr_pin_change(const char *old_pin, const char *new_pin);
|
||
|
||
/* 关闭 PIN:删 hash/salt 并把 enabled 置 0(幂等;调用方已通过锁屏验证时无需再输 PIN)。
|
||
* 返回 MR_PIN_OK / MR_PIN_ERR_STORE。 */
|
||
int mr_pin_disable(void);
|
||
|
||
/* 诊断/测试用:读回当前 hex 盐/哈希。返回 1=读成功,0=未设。 */
|
||
int mr_pin_get_salt(char *out, int outsz);
|
||
int mr_pin_get_hash(char *out, int outsz);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif /* MR_PIN_H */
|