Files
julian c142166972 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
2026-07-04 13:41:11 +02:00

152 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: decision
tags: [parking, hardening, threat-model, luks, tpm, secure-boot, grub, firmware, offline-first]
sources: [parking-system-architecture]
updated: 2026-06-30
status: settled
---
# Disk & OS hardening (booth appliance)
The host-level defences that raise the cost of **offline, physical tamper** of a booth PC: full-disk
encryption, TPM-sealed auto-unlock, Secure Boot, a GRUB edit-lock, an unprivileged operator account,
and locking firmware updates away from the operator. This page is the **rationale (the *why*)**; the
step-by-step verified commands live in the [[appliance-provisioning]] runbook (§3–5c, §4a). Settled
across the first real provisioning (2026-06-23) and the firmware-update episode (2026-06-30).
> ⚠ **This is the secondary control, not the main event.** The load-bearing anti-fraud mechanism is
> [[reconciliation]] over the [[append-only-event-chain|signed event chain]]. Disk/OS hardening
> defends the [[threat-model|outsider-with-the-box]] and raises the cost of offline tamper — it does
> **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 → **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
model defeats this.
## The five controls and why each is shaped the way it is
| Control | Choice | Why this shape (the load-bearing nuance) |
| --- | --- | --- |
| **FDE** | LUKS, **passphrase** at install (not the installer's "hardware-backed" option) | The 26.04 installer's automated FDE profiler fails on this firmware (`PCR_UNUSABLE`/`dbt`). Passphrase LUKS + a *manual* TPM seal sidesteps it and lets us pick PCRs. The passphrase slot is the **permanent recovery key**. |
| **TPM auto-unlock** | `systemd-cryptenroll`, **PCR 7 only** | Unattended reboot is a hard requirement (no operator types a passphrase). PCR 7 = Secure-Boot policy: catches the attack that matters (disabling Secure Boot) **without** churning on kernel/GRUB updates (PCRs 4/8/9 → would drop to passphrase every boot). **Keep BOTH slots** — slot 0 password (recovery), slot 1 tpm2 (auto-unlock); the TPM is never the only key. |
| **Secure Boot** | Enabled, **Deployed Mode**, stock MS keys | Ubuntu's signed shim needs stock `db`. Reaching the installer with Secure Boot ON is itself proof the MS third-party UEFI CA is trusted. |
| **GRUB edit-lock** | password, **edit-only** (`--unrestricted`) | Closes the `init=/bin/bash` root-shell hole. **The PCR-7 TPM seal does NOT cover this** — editing the cmdline doesn't change PCR 7, so the TPM still releases the key and the attacker lands on the decrypted disk. Edit-only so the box still boots **unattended** (password required only to *edit* entries). |
| **Operator account** | unprivileged, auto-login; separate **admin**+sudo | The operator is the adversary; their OS identity must not be able to escalate. Strip `sudo`, and the latent-escalation groups `lxd`/`docker` (both root-equivalent) + `lpadmin`. Admin is a distinct, no-auto-login identity. |
See [[tpm]] for the TPM-2.0 analysis (why PCR-only sealing, bus-sniff limits, TPM-vs-[[atecc608|ATECC608]]).
## Firmware / UEFI dbx updates — a hardening surface AND an operator threat
Settled 2026-06-30 after a real incident on `park-buzi`. This is the non-obvious one, because it
turns a routine "security update" into a booth-availability risk:
- **UEFI `dbx`** (the Secure Boot revocation database) and BIOS firmware are delivered by
**`fwupd`/LVFS — a channel SEPARATE from APT** (Ubuntu's GNOME "Firmware Updater" = the
`firmware-updater` snap). A clean `apt list --upgradable` does NOT mean no firmware update is pending.
- **It can brick boot:** a new dbx against a *stale* GRUB/shim **revokes the installed bootloader** →
Secure Boot refuses it → unbootable / GRUB panic. Correct order: `apt full-upgrade` (current
`grub-efi`/`shim-signed`) **first**, then dbx.
- **It breaks auto-unlock:** even with a current GRUB, applying dbx **moves PCR 7** → the TPM refuses
the LUKS key → next boot falls back to the slot-0 passphrase prompt (not a brick). Recover with the
PCR-7 re-seal runbook ([[appliance-provisioning]] §4/§4a).
- **Threat-model consequence:** a firmware/dbx update makes the booth need a passphrase to boot
unattended — so the **operator must be unable to trigger one, and must never hold the passphrase.**
Lock it down: `systemctl mask fwupd.service fwupd-refresh.timer`, `snap remove firmware-updater`,
a **BIOS admin password** that gates *entering setup* (so the operator can't disable Secure Boot /
change boot order), and the **slot-0 passphrase escrowed off-machine** (same custody as
`EVENT_SIGNING_KEY` / `BACKUP_KEY`). Firmware maintenance becomes **admin-only, on-site, deliberate**.
> The booth is unattended-bootable **only while the firmware / Secure-Boot state is frozen** — that is
> the security property, not a bug. The cost is that legitimate firmware maintenance now needs physical
> presence + the slot-0 passphrase + a PCR-7 re-enroll.
> **⚠ Verification trap:** `cryptsetup … --test-passphrase` **silently passes via the TPM token** (a
> 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
[[appliance-provisioning]]: §1 BIOS, §2 Secure-Boot live-USB check, §3 encrypted install (the `dbt`
workaround), §4 TPM seal (PCR 7) + re-seal runbook, **§4a firmware/dbx lockdown**, §5 GRUB edit-lock,
§5c admin-vs-operator accounts. Komodo Periphery is folded into the same hardened surface as a
root-capable remote agent — see [[fleet-deployment-komodo]] (bind to the NetBird interface only).
## Relates
- [[appliance-provisioning]] — the runbook (commands); this page is its *why*.
- [[tpm]] — TPM 2.0 analysis (sealing, PCR choice, limits, vs ATECC608).
- [[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.