docs(wiki): ATECC608 is upcoming — retag ledger signing to the on-host reality
No secure element is on-site: event signing runs on the software HMAC (EVENT_SIGNING_KEY, an env var on the host disk), so the ledger is tamper-EVIDENT but forgeable by anyone who owns the host. Several pages overstated it as present-tense "ATECC608-signed / unforgeable"; correct them. - NEW concepts/hardware-signer-options.md: four options for a non-extractable signing key (USB HSM / YubiKey / reuse the TPM / plain-dongle trap) + the recommendation (TPM interim → USB-HSM target; ATECC608 stays for the embedded ESP32, wrong part for a PC host). - entities/atecc608.md: UPCOMING-not-present status banner + PC-vs-embedded. - disk-os-hardening.md: fix the live-USB row (BIOS boot-order password is load-bearing, not Secure Boot — a signed live USB runs); add a physical-tamper chain (Dell 7070 CMOS-reset → live-USB → PCR-7 same-signer unseal) + accepted risks (that unseal, unsigned-initramfs evil-maid, operator-USB read TODO). - open-questions #6 reframed; standing-decisions / overview / threat-model / index de-overstated; log query entry. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -20,14 +20,27 @@ across the first real provisioning (2026-06-23) and the firmware-update episode
|
||||
> **not** replace reconciliation, and it cannot stop a *legitimate, logged-in* operator from
|
||||
> committing fraud through the app (that's what the signed ledger + reconciliation are for).
|
||||
|
||||
> ⚠ **Caveat on the ledger's tamper-resistance (2026-07-02).** The "signed event chain" above is
|
||||
> **software-signed today** (HMAC, key in `EVENT_SIGNING_KEY` on the host disk) — the [[atecc608]]
|
||||
> secure element is [[open-questions|upcoming, not present]]. So a physical adversary who *decrypts
|
||||
> the disk* (see the tamper chain below) reads the signing key and can **forge/re-sign a doctored
|
||||
> ledger undetectably** — the chain does not save you against a host-owner until a non-extractable
|
||||
> hardware signer ([[tpm|TPM]] / USB HSM — [[hardware-signer-options]]) is wired. Until then the disk's
|
||||
> confidentiality/integrity leans harder on the controls below, and the residual backstop against
|
||||
> forgery is **external reconciliation** against records the box doesn't hold (payments, an offsite
|
||||
> backup, a separate witness), not the on-disk signature.
|
||||
|
||||
## What it defends against
|
||||
|
||||
The appliance sits on-site, physically reachable by the [[threat-model|booth operator (the primary
|
||||
adversary)]] and by an outsider who can open the case. Without host hardening, either can:
|
||||
|
||||
- **Pull the SSD** and read/alter the SQLite ledger offline → FDE (LUKS) defeats this.
|
||||
- **Boot a live USB** to mount and edit the disk → Secure Boot + TPM-sealing (PCR 7) defeats booting
|
||||
a tampered/unsigned kernel; FDE keeps the data unreadable.
|
||||
- **Boot a live USB** to mount and edit the disk → **the BIOS boot-order/boot-menu password is the
|
||||
load-bearing control here**, NOT Secure Boot. Secure Boot happily runs a *signed* Ubuntu live USB,
|
||||
and PCR-7-only sealing can't distinguish it from our own boot (same signing authorities → same
|
||||
PCR 7 → the TPM would unseal). So confidentiality rests on the operator being unable to *select*
|
||||
the USB. See the physical-tamper chain below (a CMOS reset strips that password).
|
||||
- **Edit the GRUB cmdline** (`init=/bin/bash`) for a no-login root shell on the *decrypted* disk →
|
||||
the GRUB edit-lock defeats this (the TPM seal does NOT — see below).
|
||||
- **Escalate from the operator login** (sudo, `docker`/`lxd` groups) → the unprivileged-operator
|
||||
@@ -74,6 +87,50 @@ turns a routine "security update" into a booth-availability risk:
|
||||
> false safety signal). Before any firmware change, prove a *typed* passphrase still unlocks the disk
|
||||
> with `--disable-external-tokens` — see [[appliance-provisioning]] §4a.
|
||||
|
||||
## Physical-tamper chain & accepted risks (traced 2026-07-02, Dell OptiPlex 7070)
|
||||
|
||||
The BIOS admin password gates Setup **and** the one-time boot menu (verified: choosing a USB device
|
||||
at F12 prompts for the password). That closes the live-USB path — *while the password holds*. The
|
||||
uncomfortable finding is that the password is a **soft control** against a case-opening adversary:
|
||||
|
||||
1. **CMOS reset** (pull the coin cell, or the on-board PSWD/CMOS-clear jumper — Dell documents its
|
||||
location) → BIOS *settings* return to factory defaults: **admin password cleared, boot menu
|
||||
open**. It does NOT wipe the Secure-Boot key databases (PK/KEK/db/dbx live in SPI-flash NVRAM,
|
||||
not the battery-backed RTC), and the 7070's factory default is **Secure Boot = Enabled**. So
|
||||
after the reset Secure Boot comes back **on, same MS keys** → **PCR 7 reconstructs to the same
|
||||
value.**
|
||||
2. **Boot a signed Ubuntu live USB** (now selectable). Same signing authorities → PCR 7 matches the
|
||||
sealing policy → the attacker runs `cryptsetup`/`systemd-cryptsetup` and the **TPM releases the
|
||||
LUKS key**. Disk decrypts; they have **root on the decrypted filesystem**, including the ledger.
|
||||
- Note the asymmetry: if instead they *disable* Secure Boot in the now-unlocked BIOS, PCR 7
|
||||
**changes** → the TPM refuses → the box drops to the slot-0 passphrase prompt they don't have.
|
||||
So *disabling* Secure Boot locks them out; leaving it at the reset default lets them in. This is
|
||||
the PCR-7-only "same-signer" weakness (systemd docs recommend PCR 7 **+ a PIN** to close it).
|
||||
|
||||
**Net:** a battery-pull alone yields nothing (disk stays sealed), but **battery-pull → live-USB →
|
||||
PCR-7 unseal** is a realistic chain to **root on the decrypted data**. What it costs the attacker: a
|
||||
screwdriver and a signed USB. What still holds after it: they never get the **escrowed slot-0
|
||||
passphrase**, and (the point of the caveat above) the ledger's forgery-resistance depends on the
|
||||
signer — with today's **on-disk HMAC key they CAN forge the ledger**; only a hardware signer
|
||||
([[hardware-signer-options]]) would keep the financial record unforgeable through this.
|
||||
|
||||
**Accepted risks (named, not silently "covered"):**
|
||||
|
||||
- **PCR-7 same-signer unseal via CMOS reset** (above). *Not* mitigated by the current config. Real
|
||||
fixes both cost the thing we optimised for: a **TPM PIN** (`--tpm2-with-pin=yes`) closes it but
|
||||
**kills unattended boot** (someone types a PIN each power event); **custom Secure-Boot keys / more
|
||||
PCRs** close it but reintroduce re-seal churn on kernel/shim updates (the exact thing PCR-7-only
|
||||
avoids). Deferred decision — accept for now; the primary control remains reconciliation + escrowed
|
||||
backups, not disk confidentiality.
|
||||
- **Unsigned initramfs (evil-maid).** `/boot` is unencrypted and Ubuntu does **not** sign the
|
||||
initramfs (Secure Boot verifies shim→GRUB→kernel; PCR 7 doesn't measure the initrd). The initramfs
|
||||
is exactly the code that receives the LUKS key, so a maid who tampers it and waits one boot can
|
||||
harvest the key. Accepted: needs repeated privileged physical access, and a hardware signer would
|
||||
still keep the ledger unforgeable even from a fully-owned host.
|
||||
- **Operator USB at an auto-logged-in session** — unverified what the unprivileged operator account
|
||||
can read on the host (e.g. can it reach the Docker-mounted `/data`?). **TODO: verify** the operator
|
||||
can't read the DB volume or `EVENT_SIGNING_KEY` from its own login.
|
||||
|
||||
## Where the commands live
|
||||
|
||||
This page is the rationale. The **verified, run-on-real-hardware commands** are in
|
||||
@@ -89,4 +146,6 @@ root-capable remote agent — see [[fleet-deployment-komodo]] (bind to the NetBi
|
||||
- [[threat-model]] — the operator-adversary framing this hardening serves.
|
||||
- [[reconciliation]] / [[append-only-event-chain]] — the **primary** anti-fraud control this
|
||||
complements, never replaces.
|
||||
- [[hardware-signer-options]] — TPM / USB-HSM / ATECC608 options for a non-extractable ledger
|
||||
signing key (the missing piece this page's tamper chain exposes).
|
||||
- [[fleet-deployment-komodo]] — Periphery as part of the trusted computing base.
|
||||
|
||||
@@ -40,10 +40,19 @@ procurement. (See [[parking-system-architecture]] §10.)
|
||||
but **unverifiable after the machine dies**). **Restore is admin-only/out-of-band** (operator-adversary
|
||||
surface — [[threat-model]]). See [[backup-recovery]], [[fleet-deployment-komodo]], [[disk-os-hardening]],
|
||||
[[reconciliation]] (#4).
|
||||
6. **Secure-element integration.** Confirm [[atecc608]] wiring/usage on the host (event
|
||||
signing). The [[esp32-custom-controller]] command-authentication use is **deferred — not
|
||||
being implemented for now** (access control is the [[dingtian-relay]] behind
|
||||
[[network-isolation]]); revisit only if prevention-grade device auth becomes a requirement.
|
||||
6. **Secure-element integration.** _(Updated 2026-07-02: no secure element is on-site today.)_
|
||||
Event signing currently runs on the **software `SoftwareSigner`** (HMAC-SHA256, key in
|
||||
`EVENT_SIGNING_KEY` — an env var **on the host disk**). So the ledger is tamper-EVIDENT but
|
||||
**not** unforgeable by anyone who owns the host: a case-opening adversary who decrypts the disk
|
||||
reads the key and can re-sign a doctored chain (see [[append-only-event-chain]] "pull-the-disk",
|
||||
[[disk-os-hardening]] physical-tamper chain). The **[[atecc608]] is UPCOMING, not present** — and
|
||||
it isn't even the right host part: on a PC appliance the realistic non-extractable host signer is
|
||||
the **[[tpm|TPM 2.0]]** the box already has, or a **USB HSM** (Nitrokey HSM 2 / SmartCard-HSM);
|
||||
reserve the ATECC608 for the (deferred) [[esp32-custom-controller]]. The concrete menu +
|
||||
recommendation (TPM interim → USB-HSM target) is in [[hardware-signer-options]]. The
|
||||
controller command-authentication use is **deferred — not being implemented for now** (access
|
||||
control is the [[dingtian-relay]] behind [[network-isolation]]); revisit only if prevention-grade
|
||||
device auth becomes a requirement.
|
||||
7. **JWT signing: symmetric vs. asymmetric key.** _(Raised by the commit security review, not the
|
||||
source doc.)_ Auth currently uses a symmetric HMAC secret (`@fastify/jwt`, see
|
||||
[[local-jwt-auth]]) — the same secret signs *and* verifies, so it must live on every host that
|
||||
|
||||
@@ -25,9 +25,11 @@ The decisions treated as settled in the design notes. (See [[parking-system-arch
|
||||
deny-by-default native surface that fits [[threat-model|the booth-operator threat model]]. The
|
||||
shell stays **thin**: all privileged logic remains in [[fastify]]. One open dependency — the
|
||||
appliance's WebKitGTK version (see [[open-questions]] #11).
|
||||
- **Integrity:** append-only, hash-chained, [[atecc608]]-signed event log
|
||||
([[append-only-event-chain]]); **[[reconciliation]] is the anti-fraud control**; encryption
|
||||
protects only at-rest (see [[threat-model]]).
|
||||
- **Integrity:** append-only, hash-chained, **software-signed** event log
|
||||
([[append-only-event-chain]]) — hardware-backed signing (a non-extractable key in the
|
||||
**[[tpm|TPM]]** or a **USB HSM**; the [[atecc608]] is [[open-questions|upcoming, not present]]) is
|
||||
the target that makes it unforgeable by a host owner ([[hardware-signer-options]]). **[[reconciliation]]
|
||||
is the anti-fraud control**; encryption protects only at-rest (see [[threat-model]]).
|
||||
- **Access control:** the **[[dingtian-relay]]** relay+input controller, on an **isolated VLAN**
|
||||
([[network-isolation]]). Chosen because its **inputs are decoupled from its relays**, enabling
|
||||
host-in-the-loop ticket-first entry — the resolution to [[access-controller-button-flow]].
|
||||
|
||||
Reference in New Issue
Block a user