docs(series4): pin down what the ACH config's volatile field is NOT
Followed up the write[118:120] field flagged in the previous commit. A third
sample plus a brute-force sweep rules out most of the obvious explanations.
Samples: 43 23 at 00:50 (idle), still 43 23 at 01:16 twenty-six minutes later,
then 2e 5e after a config write. Thor echoes back whatever it last read --
including a value that no longer matches the config it is sending -- and the
write is accepted regardless.
Ruled out:
* a clock or timer -- identical across 26 minutes of idle; only a write moved it
* a counter -- it decreased, 17187 -> 11870
* computed by Thor -- Thor demonstrably sends a stale value
* a standard CRC16 -- swept all 65,536 polynomials x init {0x0000,0xFFFF} x all
four reflection combinations over four candidate regions.
No match. Recorded so the sweep is not repeated.
It behaves like a unit-computed hash: a one-byte input change scattered the output
(XOR 0x6D7D) where a sum would move by 1. But two samples cannot separate that
from a nonce regenerated per write.
Operationally it does not matter, which is the point: the unit does not validate
the field on input, so read-modify-write with the rest of the block echoed
verbatim is provably safe. Never synthesise or zero it.
Notes what would resolve it -- several config writes with times recorded, cheap to
collect during any future ACH capture.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
This commit is contained in:
@@ -1432,12 +1432,45 @@ bit 2 set as well in both states. Do not test for `0x01`/`0x00`.
|
||||
`write[6:]` holds the dial string, null-padded — `"RADIO RING"` on this unit,
|
||||
matching Series III's `raw[6:46]`.
|
||||
|
||||
⚠ **`write[118:120]` changed on its own between the two sessions** (`43 23` →
|
||||
`2e 5e`) without the operator touching anything. Thor reads it and writes back
|
||||
whatever it read. Its meaning is unknown — plausibly a counter, timer or
|
||||
session value. **Round-trip this field; never synthesise it.** `write[117]` is
|
||||
`0x03`, which lines up with Series III's `num_retries` of 3, and `write[120:122]`
|
||||
is `00 3c` = 60.
|
||||
#### ⚠ `write[118:120]` — a field the UNIT maintains
|
||||
|
||||
Three samples:
|
||||
|
||||
| when | enable | field |
|
||||
|---|---|---|
|
||||
| 00:50, idle (schedule session) | `0x04` | `43 23` |
|
||||
| 01:16, ACH read #1 | `0x04` | `43 23` — **unchanged after 26 min** |
|
||||
| 01:16, ACH read #2, after a config write | `0x05` | `2e 5e` |
|
||||
|
||||
Thor **echoes back whatever it last read**, including a value that no longer
|
||||
matches the config it is sending — and the write is accepted anyway.
|
||||
|
||||
What that rules out:
|
||||
|
||||
- **Not a clock or timer** — identical across 26 minutes of idle. Only a config
|
||||
write moved it.
|
||||
- **Not a counter** — it went *down*, 17187 → 11870.
|
||||
- **Not computed by Thor** — Thor demonstrably sends a stale value.
|
||||
- **Not a standard CRC16.** Brute-forced all 65,536 polynomials × init
|
||||
{`0x0000`, `0xFFFF`} × all four reflection combinations, over four candidate
|
||||
regions (`[0:118]`, `[0:118]+[120:]`, `[5:118]`, and the payload with the field
|
||||
zeroed). **No match.** Recorded so nobody repeats the sweep.
|
||||
|
||||
It behaves like a hash or checksum the unit computes over the stored config: a
|
||||
one-byte input change (`0x04`→`0x05`) scattered the output completely, XOR
|
||||
`0x6D7D`, where a sum would have moved by 1. But two samples cannot separate
|
||||
that from a nonce regenerated on each write.
|
||||
|
||||
✅ **Operationally this does not matter.** The unit does not validate the field
|
||||
on input — Thor proved that twice in one capture. **Read the config, change your
|
||||
field, send everything else back byte-for-byte.** Never synthesise or zero it.
|
||||
Same read-modify-write shape as the setup block.
|
||||
|
||||
Resolving it properly needs more samples: several config writes with the times
|
||||
noted, which is cheap to collect during any future ACH capture.
|
||||
|
||||
Neighbouring bytes: `write[117]` is `0x03`, lining up with Series III's
|
||||
`num_retries` of 3, and `write[120:122]` is `00 3c` = 60.
|
||||
|
||||
⚠ Beyond the enable byte and the dial string, **the field map is not
|
||||
established** — only one setting was varied. Series III's offsets are a starting
|
||||
|
||||
Reference in New Issue
Block a user