Skip to content

Break-glass recovery: :wipekv KV-reset, revert-to-stock tooling, stock-FW feature map - #76

Merged
AndrewDemsDS merged 4 commits into
mainfrom
feat/wipekv-revert-re-map
Jul 21, 2026
Merged

Break-glass recovery: :wipekv KV-reset, revert-to-stock tooling, stock-FW feature map#76
AndrewDemsDS merged 4 commits into
mainfrom
feat/wipekv-revert-re-map

Conversation

@AndrewDemsDS

Copy link
Copy Markdown
Owner

Summary

Three independent pieces of break-glass / recovery work, plus a reverse-engineering deliverable. Each is its own commit.

1. Stock-firmware feature map (reverse-engineering/docs/13)

Synthesizes six raw analysis passes into one map: cloud/TLS, OTA acceptance, local attack surface, the Matter stack, and the KV/sysdata layout. Notable corrections baked in:

  • XIP base is 0x9b6e0000, not the previously recorded 0x9b7d0000 (string-pointer pools only resolve at the corrected base; verified against ~20 independent pools).
  • fw2 is a different, older build (an Aug-2023 MP-test image with no Matter), so "the other slot" is not interchangeable with fw1.

Adds tools/xref.py (literal-pool + movw/movt xref finder) and gitignores the raw analysis workspace.

2. Revert-to-stock over the air, host side (ota-release.sh revert, docs §17)

Four paths, no CH341A clip required:

  • --flip — slot-flip back to the intact stock slot via the device's :slots / :revert commands
  • --backup — stream the inactive stock slot over :backup and validate it (HMAC + bytesum)
  • --repackage — carve and re-sign the stock app as a Matter OTA
  • --apply — stage and drive update_node

Documents the safety guards (the other slot must be strictly older; the cloud-binding regions stay byte-intact so a reverted unit rejoins the vendor cloud as itself) and the re-signed-image-won't-boot dead end found while testing.

3. Break-glass command handlers, device side, incl. new :wipekv (ships v1.3.16)

The device half of the recovery listener: :slots / :revert / :backup, plus a new :wipekv that factory-resets the Matter KV (formats both DCT regions) and reboots.

Why :wipekv exists. A stock unit that was ever cloud/app-paired carries its old fabric's KV entries through the OTA conversion. On an older-stock unit that leaves an orphaned root-cert blob the new firmware only half-reads, and then every commission attempt fails at SendTrustedRootCert with IM 0x0501 (deterministic, every controller and transport, survives reboot). Fabric indices allocate monotonically, so the next index is permanently stuck on the orphaned slot, and no cluster command can reach a cert whose index is not in the fabric table. :wipekv is the only cure short of a CH341A reflash.

Like the rest of the listener, :wipekv is compiled into both flavours and gated only by the break-glass token being set at build time (fails closed with no token). It is deliberately not a debug-console command, so it is present in exactly the release images most likely to need it.

Verification

  • Full recovery loop proven end to end on a real unit that was wedged at SendTrustedRootCert: :revert → re-commission stock over BLE → Matter-OTA the :wipekv-capable image → :wipekv → re-commission → handed off to the local controller with a single fabric and the reported software version confirmed by a live attribute read.
  • Host lint (codec/map tests, .zap endpoint contiguity, monotonic version) passes; version int 10316 > 10307.

Notes

  • docs/10 §13 gains a full break-glass command inventory; docs/12 documents the wedge, the no-UART diagnosis (PASE in the open window grants admin, then read the fabric table), and the recovery loop.
  • :wipekv only exists from v1.3.16 onward, so it cannot rescue an image that shipped without it. Existing deployed nodes do not have it until they are rolled forward.

AI-assisted; see the Assisted-by trailer on each commit.

…al surface, Matter, storage)

Synthesizes six raw analysis passes into docs/13: XIP base correction to
0x9b6e0000 (old 0x9b7d0000 was wrong; verified against ~20 pointer pools),
fw2 identified as an older MP-test build (no Matter), plus the OTA acceptance,
cloud/TLS, listener, and KV/sysdata layout map. Adds tools/xref.py (literal-pool
and movw/movt xref finder) and gitignores the raw analysis workspace.

Assisted-by: AI
ota-release.sh gains 'revert' with four paths: --flip (break-glass slot-flip
back to the intact stock slot via the :slots/:revert TCP commands), --backup
(stream + HMAC/bytesum-validate the inactive stock slot over :backup), --repackage
(carve and re-sign the stock app as a Matter .ota), and --apply (stage + drive
update_node). docs/10 §17 documents all four, the safety guards (other slot must
be strictly older; cloud-binding regions stay byte-intact), and the Path-2
re-signed-image-won't-boot dead end.

Assisted-by: AI
…wipekv

Device-side break-glass command suffixes on the #61 listener: :slots / :revert /
:backup (the #19 firmware half; host tooling in the prior commit) and the new
:wipekv (>= 1.3.16). :wipekv calls deinitPref() to format both Matter DCT regions
then reboots, curing the commissioning wedge on stock units with a cloud-pairing
history: an orphaned stock-era root-cert blob makes every commission fail at
SendTrustedRootCert (IM 0x0501), unreachable by any cluster command. docs/10 §13
gains the command inventory; docs/12 documents the wedge, the diagnosis (PASE +
read fabrics), and the recovery loop. Proven on the office unit -> node 62.

version.txt -> 1.3.16.

Assisted-by: AI
The unused imm4i() helper computed i/imm4/imm8 then returned None; the real
movw/movt decode is inline below it. Removed so ruff F841 passes CI.

Assisted-by: AI
@AndrewDemsDS
AndrewDemsDS merged commit 9504c4d into main Jul 21, 2026
7 checks passed
@AndrewDemsDS
AndrewDemsDS deleted the feat/wipekv-revert-re-map branch July 21, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant