From bb9e18274d9431370b20428de2bba89573b3de04 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 02:59:18 +0200 Subject: [PATCH 1/2] fix(L1): gate [door]/[storage] enumeration prints behind HSLOCK_DEBUG (off in release) Co-Authored-By: Claude Opus 4.8 (1M context) --- main.c | 11 ++++++----- shared/debug.h | 28 ++++++++++++++++++++++++++++ storage/storage.c | 4 +++- 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 shared/debug.h diff --git a/main.c b/main.c index 4583119..5985371 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,7 @@ #include "storage/storage.h" #include "hardware/sync.h" +#include "shared/debug.h" #include "shared/door_verify.h" #include "shared/totp.h" @@ -67,15 +68,15 @@ static void core0_handle_door_verify(void) { key_record_t key; if (!storage_key_get(id, &key)) { - printf("[door] key %u: not found\r\n", id); + DBG("[door] key %u: not found\r\n", id); } else if (!key.is_checksum_valid) { - printf("[door] key %u: corrupt\r\n", id); + DBG("[door] key %u: corrupt\r\n", id); } else if (!key.is_enabled) { - printf("[door] key %u: disabled\r\n", id); + DBG("[door] key %u: disabled\r\n", id); } else if (!totp_verify(key.secret, KEY_SECRET_LEN, code)) { - printf("[door] key %u: invalid code\r\n", id); + DBG("[door] key %u: invalid code\r\n", id); } else { - printf("[door] key %u (%s): granted\r\n", id, key.name); + DBG("[door] key %u (%s): granted\r\n", id, key.name); granted = true; } diff --git a/shared/debug.h b/shared/debug.h new file mode 100644 index 0000000..e9b36fd --- /dev/null +++ b/shared/debug.h @@ -0,0 +1,28 @@ +#ifndef HSLOCK_DEBUG_H +#define HSLOCK_DEBUG_H + +// Compile-time gate for diagnostic console output. +// +// Some diagnostics leak security-relevant information over the USB console +// (key-id enumeration, holder names, per-grant occupancy). They are useful +// during development but must NOT be present in a shipped build, where anyone +// with a cable could passively read a live occupancy/attendance log. +// +// DBG(...) expands to printf(...) only when HSLOCK_DEBUG is a non-zero value; +// otherwise it expands to nothing (arguments are NOT evaluated). Define +// HSLOCK_DEBUG=1 (e.g. via -DHSLOCK_DEBUG=1) to re-enable the diagnostics. +// The shipped build leaves it at the default of 0. + +#include + +#ifndef HSLOCK_DEBUG +#define HSLOCK_DEBUG 0 +#endif + +#if HSLOCK_DEBUG +#define DBG(...) printf(__VA_ARGS__) +#else +#define DBG(...) ((void)0) +#endif + +#endif // HSLOCK_DEBUG_H diff --git a/storage/storage.c b/storage/storage.c index 454e32f..1d27e02 100644 --- a/storage/storage.c +++ b/storage/storage.c @@ -1,6 +1,8 @@ #include "storage.h" #include "shared/wipe.h" +#include "shared/debug.h" + #include "lfs.h" #include "lfs_util.h" #include "pico/stdlib.h" @@ -310,7 +312,7 @@ bool storage_key_get(uint16_t id, key_record_t *out) { secure_wipe(&stored, sizeof(stored)); if (!out->is_checksum_valid) - printf("[storage] key %u checksum mismatch\r\n", id); + DBG("[storage] key %u checksum mismatch\r\n", id); return true; } From ba0c9c851664d060b826e783482ad54cb5bc69ea Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 20:26:42 +0200 Subject: [PATCH 2/2] fix(cmd_status): function-scope keys so the coverage/firmware build compiles Rebasing onto current master pulled in a latent build break: cmd_status declares `keys` inside the `if (commands_is_admin())` block but scrubs it via `secure_wipe(keys, sizeof(keys))` at function scope, so `keys` is undeclared there. asan_commands links serial/commands.c (not commands_system.c) so it never compiled this TU, but `make -C test coverage` compiles the whole first-party surface and fails here (`keys undeclared`) -- as does the real firmware build. Restore `keys` to function scope, matching the scrub's intent of always clearing the key DB from BSS (incl. the non-admin path where it stays zero-initialised). Same fix as PR #15 (M1). Co-Authored-By: Claude Opus 4.8 (1M context) --- serial/commands_system.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/serial/commands_system.c b/serial/commands_system.c index 4b92f9e..bdd3cac 100644 --- a/serial/commands_system.c +++ b/serial/commands_system.c @@ -64,11 +64,13 @@ void cmd_status(int argc, char **argv) { printf("ntp: not synced\r\n"); } - // Keys (admin only: key inventory is target-selection data) + // Keys (admin only: key inventory is target-selection data). Declared at + // function scope so the scrub below always runs, even on the non-admin path + // where the array stays zero-initialised. + static key_record_t keys[BACKUP_MAX_KEYS]; if (commands_is_admin()) { - static key_record_t keys[BACKUP_MAX_KEYS]; - int count = storage_key_list(keys, BACKUP_MAX_KEYS); - int enabled = 0, corrupt = 0; + int count = storage_key_list(keys, BACKUP_MAX_KEYS); + int enabled = 0, corrupt = 0; for (int i = 0; i < count; i++) { if (!keys[i].is_checksum_valid) corrupt++;