docs(10-06): plan KEY-05 crate-wide defaulted-RNG enforcement
Adds 10-06-PLAN.md covering KEY-05 (F-10a / R-16). 10-01..10-05 untouched. Six tasks, sequenced so CI stays green at every intermediate commit: classify all 43 call sites with file:line evidence; a tracer that wires the sealed KeyGenRng allowlist, the degenerate-entropy predicate and the CSPRNG readiness ledger end-to-end through the mnemonic seam; two migration tasks; a blocking human checkpoint for cargo-deny scope and legitimacy; then the gates are enabled last and observed failing a real build. The clippy ban is a compile failure under the existing -D warnings CI step, so core/clippy.toml is deliberately not committed until every site -- including test code, since --all-targets counts it -- has migrated. Wave 2: shares seed.rs with 10-05 and api/rpc/auth.rs with 10-01. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5718179e2f
commit
dba3a30af9
@@ -269,7 +269,7 @@ Plans:
|
||||
**Goal:** Every path that creates, restores, or persists node key material proves the caller is authorized and the material is per-node — closing the three exploitable findings from `docs/security/ENTROPY-SEED-AUDIT-2026-07-31.md`. A node that is already onboarded must refuse to have its identity replaced; a node flashed from the shared rootfs must never share another node's host keys; and the wallet spending key must not exist in cleartext outside the encrypted envelope.
|
||||
**Requirements**: KEY-01 (F-01, **Critical**) `seed.generate`/`seed.restore` are unauthenticated (`api/rpc/middleware.rs:25`) and `NodeIdentity::from_seed` (`identity.rs:79`) overwrites `node_key`/`nostr_secret`/FIPS key unconditionally — one unauthenticated POST with an attacker-chosen mnemonic hijacks a live node; gate on onboarding-incomplete (the unused `identity.rs:117` `key_exists` guard) + rate-limit; KEY-02 (F-03, **High**) first-boot per-device secret regeneration is fail-open and its completion marker is set even on failure (`image-recipe/_archived/build-auto-installer-iso.sh:1647,:1659,:1663`), over a fleet-shared cached rootfs that bakes SSH host keys + the TLS key — make it fail-closed and retried; KEY-03 (F-13, **High**) the BIP-84 account **private** key is imported into Bitcoin Core's wallet (`api/rpc/bitcoin.rs:203,:229-231`), duplicating the spending key outside the encrypted envelope — move to watch-only descriptors per `docs/security/PSBT-SIGNING-ARCHITECTURE.md`; KEY-04 on-node verification of C-3/C-4/C-6 from the audit's UNVERIFIED checklist (host-key uniqueness across two real nodes, rootfs tar contents on the build host, unauthenticated LAN reachability of the RPC endpoint); KEY-05 (F-10a, **Medium**, added 2026-08-02) **a defaulted RNG cannot be inherited anywhere in the crate**. The audit's F-10 recorded this as 2 call sites; it is **41 across 15 files** (`session.rs` 16, `pine_ha.rs` 6, `wallet/bdhke.rs` 4 — *ecash key material*, `mesh/x3dh.rs` 2 — *key-agreement material*, `storage_crypto.rs` 1 — *AEAD nonce*, +10 more; full table in the audit's §F-10a). Nothing is broken today — `rand::random()`/`thread_rng()` are ChaCha12 seeded from `getrandom(2)` — but this is the exact T1 structural shape that produced the 2026-07-30 COLDCARD defect, now with key material in its blast radius. Five layers, all required: (a) **sealed allowlist trait** at key-generation seams (private supertrait, so no other module *or crate* can implement it; exactly one production impl, `OsRng`) — this also retires the `impl rand::CryptoRng for CountingRng` false promise at `seed.rs:656`; (b) **`clippy.toml` `disallowed-methods`** banning `rand::thread_rng`/`rand::random` crate-wide, so enforcement is a compile failure in CI rather than a review convention (no `clippy.toml` exists today; CI already runs clippy); (c) **`cargo-deny`** failing on duplicate `rand` majors — two coexist today, which is the mechanism by which a bump could silently rebind (absorbs R-05); (d) **degenerate-entropy runtime check** before key generation (rejects all-zero / counter-like draws — the one layer that would catch the Coldcard failure *on the device* rather than in review); (e) **persist the CSPRNG-readiness verdict** that `seed.rs:59` already computes and discards, so a node can answer after the fact "was the pool seeded when this key was born?" (absorbs R-09). Supersedes R-13
|
||||
**Depends on:** Nothing (independent security work; parallelizable with Phases 1–8). **Priority override: F-01 is Critical and live on every fleet node — this phase should be planned and executed ahead of its numeric position, which reflects append order in a shared roadmap, not sequencing.**
|
||||
**Plans:** 5 plans + KEY-05 unplanned (needs a 6th plan)
|
||||
**Plans:** 6 plans
|
||||
|
||||
> **EXECUTION GATE (user instruction, 2026-08-02):** do **not** begin executing this phase until
|
||||
> (a) the concurrent agent working Phase 1 has finished, and (b) their changes are synced and
|
||||
@@ -277,8 +277,9 @@ Plans:
|
||||
> `bitcoin.rs` and — under KEY-05 — ~15 further files across the same crate that agent is
|
||||
> actively committing to. Verify a clean tree and a fetched `gitea-ai/main` before starting.
|
||||
>
|
||||
> **KEY-05 is not yet planned.** The 5 plans below predate it; a 6th plan (or a re-plan) is
|
||||
> required before this phase can be considered fully covered.
|
||||
> **KEY-05 is planned** as `10-06` (added 2026-08-02). The other 5 plans predate KEY-05 and
|
||||
> are unchanged by it. `10-06` is wave 2 because it shares `seed.rs` with `10-05` and
|
||||
> `api/rpc/auth.rs` with `10-01`; see its `<file_collision_analysis>`.
|
||||
|
||||
Plans:
|
||||
|
||||
@@ -292,6 +293,7 @@ Plans:
|
||||
|
||||
- [ ] 10-02-PLAN.md — On-node C-6 exposure measurement, live refusal proof, and the fresh-node onboarding non-regression (KEY-01/KEY-04) — depends on 10-01
|
||||
- [ ] 10-04-PLAN.md — Fleet detection of image-baked host secrets, guarded one-time rotation, and C-3 two-node verification (KEY-02/KEY-04) — depends on 10-03
|
||||
- [ ] 10-06-PLAN.md — A defaulted RNG cannot be inherited anywhere in the crate: sealed allowlist, clippy ban, cargo-deny, degenerate-entropy check, persisted CSPRNG verdict (KEY-05) — depends on 10-01 and 10-05
|
||||
|
||||
### Phase 11: Wallet Experience & LND UI Parity
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user