Files
parking_solution/wiki/concepts/hardware-signer-options.md
T
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

91 lines
5.5 KiB
Markdown
Raw 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: concept
tags: [parking, security, integrity, crypto, hardware, threat-model]
sources: []
updated: 2026-07-02
---
# Hardware signer options (non-extractable ledger signing key)
Where the **[[append-only-event-chain|signed ledger]]'s** private signing key should live so that an
adversary who **owns the host** — including one who decrypts the disk via the [[disk-os-hardening]]
physical-tamper chain — still cannot **forge** the ledger. This is the still-open
[[open-questions|open-question #6]], reframed once it became clear (2026-07-02) that **no secure
element is on-site** and the [[atecc608]] isn't even the right part for a PC.
## The problem in one line
Today signing uses the software `SoftwareSigner` — **HMAC-SHA256, key in `EVENT_SIGNING_KEY`, an env
var on the host disk**. HMAC is symmetric: the same secret signs *and* verifies, and it sits on the
box. So the chain is tamper-**evident** (a blind editor without the key breaks it, and `verifyChain()`
pinpoints where) but **not unforgeable** — anyone who reads the key re-signs a doctored chain and it
verifies clean. The fix is a signer whose **private key is non-extractable**: the host can ask it to
sign, but can never read the key. That is a property of an HSM / smartcard / TPM — **not** of anything
that merely *stores* a key.
## The four options
### 1. USB HSM — Nitrokey HSM 2 / SmartCard-HSM *(recommended target)*
A ~€50 USB device with a non-extractable EC key (secp256r1 — same curve family as the ATECC608). The
host signs each event over **PKCS#11**; the key never leaves the token. It's essentially "the
ATECC608, but on USB instead of soldered", so it drops into the existing `signer.ts` seam (the
`keyId` field + the `TODO(atecc608)` public-key-verifier hook).
- **License fit:** OpenSC (the PKCS#11 stack) is LGPL/permissive — no vendor lock-in, matches the
all-MIT/Apache/BSD [[technology-stack|stack constraint]].
- **Downside:** it's *removable* — an operator can pocket it. But that fails **closed** (no token →
can't sign → visibly noticed), and it can be epoxied / locked inside the case.
### 2. YubiKey (PIV or OpenPGP applet)
Also a non-extractable EC/RSA key over PKCS#11; very robust, widely deployed; works the same way as
the Nitrokey for this purpose. Slightly more oriented to human 2FA than to an always-present signing
oracle, and the vendor stack is less fully-open than OpenSC. **~$50–70.** Fine as a substitute for
option 1.
### 3. Reuse the on-board TPM 2.0 *(recommended interim — free)*
The booth PC already has a TPM (it's what seals LUKS — [[tpm]]). A TPM can also hold a non-extractable
signing key and sign over it. **Zero extra hardware, closes the "key in a plaintext env file" hole
immediately.**
- **The nuance:** don't reuse the *LUKS* sealing arrangement. That key is PCR-7-sealed, and the
battery-pull → live-USB → PCR-7 chain ([[disk-os-hardening]]) defeats PCR-7-only policies. Bind the
**signing** key to the TPM **without a PCR policy** (or with a PIN) so it's about non-extractability,
not boot-state — then an attacker who decrypts the disk still can't pull it.
- **Weaker than a dedicated HSM** against a sophisticated bus-sniffing attacker, but far stronger than
today's on-disk HMAC.
### 4. Plain USB "sentinel" / dongle *(the trap — avoid)*
A generic USB flash drive holding a key file, or a license-dongle that only gates "is this USB
present". **Useless here:** if the key is *readable* off the stick, the host-owner copies it, exactly
like the env var. Presence-gating is not integrity. Only a device that **signs internally** delivers
non-extractability. Do not go this route.
## Recommendation
1. **Now (free):** move signing to a **TPM-held key** (option 3, no PCR policy) — kills the
plaintext-key-on-disk exposure using hardware already present.
2. **Target (purchasable):** a **USB HSM (Nitrokey HSM 2)** as the concrete stand-in for the still-
planned [[atecc608]] — same non-extractable-EC model, fits `signer.ts`, open tooling; physically
lock it in the case.
3. **[[atecc608]]** stays reserved for the **deferred** [[esp32-custom-controller]] (embedded), not
the PC host.
Whichever is chosen, the code seam already exists: each event stores its `keyId`, so a swap is a new
`Signer` impl and **old events stay verifiable** under their original key — no migration of history.
## The mental model to keep
Against the physical adversary who opens the case, **the only real protection for the financial
record is a signing key even root can't read.** That is an HSM/smartcard/TPM property, never a
USB-storage property — and it's precisely what's missing today. Note the layering: [[disk-os-hardening]]
raises the cost of *reaching* the disk; a hardware signer makes the ledger unforgeable *even after*
the disk is reached; and [[reconciliation]] against records the box doesn't hold is the backstop that
survives a fully-owned host. They are complements, not substitutes.
## Relates
- [[append-only-event-chain]] — the ledger this key signs; why software signing isn't enough.
- [[atecc608]] — the originally-specified secure element (upcoming; embedded, not PC).
- [[tpm]] — the on-board part; option 3, and the LUKS-sealing analysis.
- [[disk-os-hardening]] — the physical-tamper chain that makes a non-extractable key necessary.
- [[open-questions]] #6 (secure-element integration), #7 (JWT symmetric→asymmetric — same key-custody
argument for auth tokens).
- [[threat-model]] / [[reconciliation]] — the adversary and the backstop control.