Living decision doc (started 2026-09-25). Locks on the ATECC608 are permanent, so each one gets decided here first, with evidence, before anyone holds A on a red screen. Record what was done, and when, in the buildlog.
0123f3acfd2a826bee, the dev console’s only chip| Part | ATECC608A, revision 00006002 |
| Config zone | locked (2026-09-17) |
| Data zone | open |
| Slot locks | none (bytes 88–89 = ff ff) |
| Config | Byte for byte, the wallet table in firmware/atecc.py, which is cryptoauthlib’s test_ecc608_configdata, Microchip’s test config. The only byte that differs is 52, where the chip keeps counter 0. |
| Counter 0 | 7 |
| Slot | Kind | Key | Lockable | Notes |
|---|---|---|---|---|
| 0 | P-256 private | 9fad2e82… |
yes | GenKey allowed. LimitedUse: every signature counts against counter 0. The console’s key. |
| 2 | P-256 private | 82004df5… |
no | GenKey allowed. Can never be sealed: a scratch key. |
| 7 | P-256 private | empty | yes | GenKey, and PrivWrite (an encrypted import) |
| 10 | “AES”, clear writes always, not secret | never written | yes | CountMatch limit slot (config byte 18 = 0xA1) |
These checks are free, read only, and move no funds.
0x2843705391b7E2cf06b0b964b532Ad9891535E530x3ca6AE8f102083B8290Adc96A653C6580C19594FThese come from firmware/webauthn.py, and the deployed passkey factory’s getSigner agrees on
Base Sepolia, Base and Ethereum. Neither proxy is deployed yet.
isValidSignatureForSigner returned 0x1626ba7e on all three chains, for the signature as
signed (high s) and normalized to low s.0x00000000.The sources are the ATECC608A full datasheet (a preliminary copy, the only one public), the ATECC508A complete datasheet (DS20005927A), and cryptoauthlib. Confidence is high unless marked.
ff, never written) and freezes the “never write” slots
with whatever the factory left in them. It gives up slot 7’s encrypted import unless slot 4’s
secret is set first.0x0F from then on.E0 FF 1F 00 E0 FF 1F 00 followed by 24
zeros (cap 2,097,120, the value Microchip’s own test restores). Read it back after the lock,
then lock slot 10 so nobody can lower it.Not verified on silicon: the Lock error code for a refused lock, CountMatch before the data lock, and the factory contents of the data slots.
Fresh chips don’t get this table. They get quorum v1: one sealed signing key, slots 1-15 dead, CountMatch off, and each zone locked against a CRC the chip checks. The ceremony is in the ceremony image. See PROVISIONING.md.
Chip #1 stays as it is. The console pins it with QUORUM_EXPECT = {"serial": "0123f3acfd2a826bee",
"slot": 0, "owner": "0x2843705391b7E2cf06b0b964b532Ad9891535E53", "locked": True} (tools/fw pin).
The chip map no longer writes the test table or locks a zone without a CRC. Its data zone stays
open: no CountMatch trap is sprung.
Slot 0 only, after rung 2. Done: slot 0 is sealed and the data zone is still open. Slot 2 is the scratch key and slot 7 is free. The next chips get their own config and a full ceremony.
getSigner on Base Sepolia, Base, Ethereum0xdb29…0788),
isValidSignatureForSigner = 0x1626ba7e on Base Sepolia, Base and Ethereum. Counter 0 went
7 → 8 (2026-09-25).0x2843…5e53 for “This key” itselflive exec
executed it: Safe 0xEDED…0a43 #1, tx
(2026-09-25). The Pico signed, but its own POST failed on memory (OSError 12), so its held
signature was posted from the laptop unchanged. The firmware fix is in txservice.py.ALLOW_GENKEY = False on the board before the lock. Slot 0’s menu has NEW KEY beside LOCK
SLOT, and one slip would replace the enrolled key and then seal the wrong one.fe ff (bit 0 clear). Config still locked (00), data zone still open (55).9fad2e82…da78e178… byte for byte: the sealed key is the enrolled owner 0x2843…5E53isValidSignatureForSigner on Base
Sepolia, Base and Ethereum, and the Pico’s own proxy’s isValidSignature on Base SepoliaALLOW_LOCK and ALLOW_GENKEY both False on the board