Claude
Skills
Sign in
Back

chain-of-trust-design

Included with Lifetime
$97 forever

Decision aid for bootstrap and verification chains — forces the 'what authenticates the authenticator' question; patterns for signed bootstrap, measured boot, recovery.

Design

What this skill does


# chain-of-trust-design

Decision aid for the integrity chain that protects a system from first byte executed to first secret derived. Use this skill when designing or reviewing any system that has a "boot" step, an "unlock" step, or a "first run" step where code outside your trust boundary must be trusted to load code inside it.

The skill exists to force the question almost everyone forgets: **what authenticates the code that authenticates everything else?**

## Triggers

Primary phrases match automatically. Alternates:

- "bootstrap signing" / "signed bootstrap"
- "evil maid" / "physical access attacker"
- "measured boot" / "TPM attestation"
- "verify the verifier"
- "unsigned scripts" / "is this script trusted"
- "first-run integrity"
- "USB boot integrity"

## When NOT to use this skill

- Networked TLS chain-of-trust (different domain — use a peer-reviewed PKI design)
- Code-signing for application updates *after* boot (use Sigstore, signify, or platform store; this skill is about the layer below)
- Software-supply-chain trust *upstream* of build (handled by `supply-chain-trust` skill — Tier 2)

---

## Section 1: The core question

Every system that processes secrets has a chain of code, where each link must trust the previous one. The chain typically looks like:

```
firmware → bootloader → kernel → init/userland → application → secrets
```

Or, in a portable-secrets context:

```
travel-host firmware → BIOS → USB boot → unlock.sh → LUKS unlock → install-pkgs.sh → secrets pipeline
```

For each arrow, ask: **what authenticates the next link?**

If the answer is "the previous link verifies a manifest" — fine, but then ask: **what authenticates the previous link?** Trace it all the way back. The chain MUST terminate at:

- A **hardware root of trust** (TPM PCR measurement, Secure Boot pubkey in firmware), OR
- An **operator-carried secret** (a printed hash card, a signed binary on a piece of media you carry physically), OR
- An **assumption** (e.g., "the firmware is trusted") that is documented and accepted

If the chain terminates in a circular reference — "the manifest verifies the scripts, the scripts verify the manifest" — you have **no chain of trust at all**. This is the failure mode in review finding B3.

---

## Section 2: Anti-patterns (BLOCK on these)

### Circular trust

```
unlock.sh on FAT32 partition
  ↓ (verifies)
manifest.sha256 on FAT32 partition
  ↓ (lists hash of)
unlock.sh on FAT32 partition
```

Both files live on unauthenticated media. An evil-maid attacker swaps `unlock.sh` AND `manifest.sha256` consistently. Detection: zero. → **BLOCK**

### Unsigned bootstrap on writable media

Any executable on writable storage that runs before the integrity chain is established. → **BLOCK**

### "Override" prompt on integrity failure

```
[!] Manifest verification failed. Type Y to continue:
```

Operators learn to autoresponse-Y. The override defeats the integrity check on the exact pathway integrity matters most: when something is wrong. → **BLOCK** (see `degraded-mode-design` skill, Tier 2, for the multi-step ceremony alternative)

### "We use SHA-256 of the scripts" without offline-signed pubkey

Hashing is not signing. Anyone with write access to the manifest can replace it. Hashing only authenticates if the hash itself is delivered through a separately-trusted channel (printed card, hardware-fused).

### Scripts that mount LUKS before integrity is verified

The unlock script IS the high-value target. Verify its integrity before running it, or you've gained no security from LUKS.

---

## Section 3: Pattern catalog

Pick at least one. The patterns are not mutually exclusive — defense in depth combines two or more.

### Pattern A: Signed bootstrap blob with offline key

**Shape**: Ship `bootstrap.tar` plus `bootstrap.tar.sig` plus a small static-linked verifier (`verify`) on the same media. The verifier has an embedded ed25519 public key. The private key is offline (HQ, hardware-stored).

```
USB layout:
  /verify              ← static, ~50 KB, embedded pubkey
  /bootstrap.tar       ← contains unlock.sh, install-pkgs.sh, .deb files, manifests
  /bootstrap.tar.sig   ← Ed25519 signature over bootstrap.tar

Operator runs:
  ./verify bootstrap.tar bootstrap.tar.sig && tar xf bootstrap.tar && ./unlock.sh
```

**What this gives you**: Evil-maid swap of `unlock.sh` requires also forging an Ed25519 signature → infeasible without HQ private key.

**What this does NOT give you**: Trust in `verify` itself. The verifier is on the unauthenticated media. Mitigations:

1. Make `verify` minimal and reproducibly built — anyone can audit it
2. Print a SHA-256 of `verify` on a card the operator carries; check before running
3. Better: combine with Pattern B or C

**Suggested defaults**:
- Signature: Ed25519 via libsodium or Rust `ring`
- Verifier build: Rust with `#![no_std]`, statically linked, reproducibly built
- Key custody: offline, hardware-token-protected (FIDO2 PRF or HSM)

**Vetted alternatives**:
- `signify` (OpenBSD) — minimal verifier already exists; use if you want zero custom code
- `minisign` — `signify` with extras (prehashed mode)
- Sigstore Cosign — heavier, network-aware; pick when you want transparency log integration

### Pattern B: Signed live image (Tails-style)

**Shape**: The "operating environment" is itself the signed thing. Boot from a signed read-only image; the USB you carry only contributes data, not code.

```
Travel host:
  → BIOS verifies bootloader signature (Secure Boot)
  → Bootloader verifies live-image signature
  → Live image kernel + userland is read-only
  → User USB plugs in for data only

Threat collapses to: trusted firmware + your USB.
```

**What this gives you**: Massive blast-radius reduction (review finding H4). The travel host stops being a trust dependency.

**What this does NOT give you**: Protection against firmware-level adversary or hardware implant. Combine with Pattern C.

**Suggested defaults**:
- Build: NixOS image (reproducible by construction) OR Tails (community-vetted, anonymity-focused)
- Signing: integrate with the distro's existing signing (NixOS: `nix-store --verify`; Debian-based: signed `Release` file)
- Boot: Secure Boot with operator-controlled keys (sbctl), not Microsoft's defaults

### Pattern C: Measured boot + TPM remote/local attestation

**Shape**: TPM measures every stage of boot into PCRs. Refuse to derive secrets if PCRs don't match a known-good set.

```
PCR measurements taken at:
  PCR 0    — firmware
  PCR 4    — bootloader
  PCR 7    — Secure Boot policy
  PCR 8    — kernel + initrd
  PCR 9    — kernel command line

Unlock requires: TPM2_Unseal succeeds against the known-good PCR set
```

**What this gives you**: Binds secret access to a non-tampered boot chain. Evil-maid swap → PCRs change → unseal fails → no secrets.

**What this does NOT give you**: Anything if the TPM is compromised, the firmware is malicious, or the operator is coerced into running with sealed values that match a malicious chain ("seal your secret to my malicious kernel").

**Suggested defaults**:
- Tooling: `systemd-cryptenroll --tpm2-pcrs=...`, `tpm2-tools`, `clevis` for higher-level sealing
- PCR set: 0, 2, 4, 7, 8 (firmware, option ROMs, bootloader, Secure Boot policy, kernel)
- Backup unseal: secondary path with hardware token (review finding H5: backup story)

### Pattern D: Printed hash card (operator-carried)

**Shape**: The operator carries a piece of paper (or laminated card) with a SHA-256 of the bootstrap blob. Manually compares before running.

```
Card:
  bootstrap.tar.sig SHA-256:
  a1b2 c3d4 e5f6 0708 1a2b 3c4d 5e6f 7081
  9a8b 7c6d 5e4f 3021 1a2b 3c4d 5e6f 7080

Operator runs:
  sha256sum bootstrap.tar.sig
  # compares first/last 4 groups against card
```

**What this gives you**: A truly out-of-band trust anchor, immune to USB tampering.

**What this does NOT give you**: Operational ergonomics; it's tedious and skipped under time pressure. Use as a SECONDARY check, not the 

Related in Design