Skip to content

feat: emergency all-hands wipe broadcast — YubiKey-signed fleet-wide crypto-destruction #36

Description

@nielsweistra

Problem

There is no mechanism to trigger fleet-wide crypto-destruction in a mass-compromise or mission-abort scenario. Currently each device must be individually revoked or wiped, which is too slow when an entire field deployment is at risk.

Solution — Emergency All-Hands Wipe Broadcast

A single YubiKey-signed broadcast message triggers crypto-destruction on ALL active field devices simultaneously.

Server endpoint

POST /api/v1/mission/broadcast/destroy
Authorization: Bearer <operator_jwt>
Content-Type: application/json

{
  "operator_id": "niels.weistra",
  "broadcast_nonce": "base64-random-32-bytes",
  "issued_at": "2026-05-14T18:45:00Z",
  "signature": "base64-ecdsa-p384-signature-over-payload"
}

Signature covers: operator_id + broadcast_nonce + issued_at — verified against stored operator ECDSA P-384 public key.

Replay protection

  • issued_at must be within 30 seconds of server time
  • broadcast_nonce stored in Redis with 60s TTL — duplicate submissions rejected

Fan-out

Server marks ALL MachineStatus.mission_active machines as destroying and:

  1. Fans out wipe signal to all connected itl-tpm-register agents (via long-poll or webhook)
  2. Each agent: clears LUKS key slot 0 (TPM-sealed), wipes AES keys from memory, writes destruction event to TPM NV

Audit

# models/broadcast.py
class BroadcastEvent(Base):
    id: uuid
    operator_id: str
    broadcast_nonce: str
    issued_at: datetime
    machines_targeted: int
    executed_at: datetime
    signature_verified: bool

Authorization

Requires itl-broadcast-operator Keycloak role — separate from itl-cell-admin. Requires YubiKey-backed token (enforced via Keycloak auth flow policy).

MITRE ATT&CK

  • T1485 — Data Destruction (authorized defensive use)
  • T1486 — Data Encrypted for Impact (reverse: decrypt and destroy own keys)

Files

  • New: routers/broadcast.py
  • New: services/broadcast_wipe.py
  • New: models/broadcast.py
  • New env var: ITL_BROADCAST_OPERATOR_PUBKEY_PATH

Companion issue

  • ITL.Talos.HardenedOS: itl-tpm-register broadcast wipe receiver

Acceptance Criteria

  • Unsigned or expired broadcast → 401 / 403
  • Valid signed broadcast → all active mission machines transition to destroying
  • Broadcast event logged to broadcast_events table (append-only)
  • Replay of same broadcast_nonce within 60s → 409
  • itl-broadcast-operator role required (not standard admin)
  • Test: valid broadcast → N machines marked destroying; replayed broadcast → 409
  • Rate limit: max 1 broadcast per 10 minutes (hard limit, not configurable)

Metadata

Metadata

Assignees

No one assigned

    Labels

    effort:13Effort score 13 (Fibonacci)impact:5Impact score 5 (Fibonacci)military-gradesecuritySecurity vulnerability or hardeningtype:storyUser story -- a piece of deliverable value

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions