# Threat Model

## System Overview

quicprochat is a production-grade end-to-end encrypted group messenger built in Rust. It provides confidential group messaging using the MLS protocol (RFC 9420) for group key agreement, with a hybrid post-quantum key encapsulation mechanism (X25519 + ML-KEM-768) to protect against future quantum adversaries.

### Architecture

```text
+------------------+           +-------------------+           +------------------+
|  Client A        |   QUIC    |   quicprochat     |   QUIC    |  Client B        |
|                  |<--------->|   Server           |<--------->|                  |
|  - MLS group     |  TLS 1.3  |                   |  TLS 1.3  |  - MLS group     |
|    state machine |           |  - Auth Service    |           |    state machine |
|  - Hybrid KEM    |           |  - Delivery Svc    |           |  - Hybrid KEM    |
|  - Ed25519 ID    |           |  - Key Transparency|           |  - Ed25519 ID    |
|  - OPAQUE client |           |  - OPAQUE server   |           |  - OPAQUE client |
|  - Sealed sender |           |  - Rate limiting   |           |  - Sealed sender |
+------------------+           +-------------------+           +------------------+
                                       |
                               +-------+-------+
                               |               |
                          +----+----+    +-----+-----+
                          | SQLite/ |    | Federation |
                          |SQLCipher|    |   Peers    |
                          +---------+    +-----------+
```

### Protocol Stack

```text
QUIC (quinn) + TLS 1.3 (rustls)
  +-- Session auth (OPAQUE token handshake)
      +-- RPC framing [method_id:u16][req_id:u32][len:u32][protobuf]
          +-- MLS (openmls 0.8) — group key agreement, epoch rotation
              +-- Hybrid KEM (X25519 + ML-KEM-768) — HPKE init keys
                  +-- Sealed sender — Ed25519-signed inner envelope
                      +-- Padded application messages
```

## Trust Boundaries

### B1: Client to Server

The client communicates with the server over QUIC + TLS 1.3. The server is authenticated via its TLS certificate. The client authenticates via OPAQUE (password-authenticated key exchange), receiving a session token.

**Trust assumption**: The server correctly routes messages but cannot read their content. The server is a semi-trusted relay; it sees encrypted MLS blobs, metadata (group IDs, sender/recipient identity key fingerprints, timestamps, message sizes), and connection information (IP addresses).

### B2: Server to Federation Peer

Federation peers communicate over mutual-TLS QUIC connections. Each server authenticates the other via certificate pinning or a CA trust chain.

**Trust assumption**: A federated peer is trusted to relay messages to its local users but is not trusted with message content (MLS blobs are opaque). A compromised federation peer can drop, delay, or reorder messages but cannot forge or decrypt them.

### B3: Server to Storage

The server stores OPAQUE registration records, user identity keys, KeyPackages, group metadata, and message queues in SQLite. Client-side local storage uses SQLCipher (AES-256-CBC) with Argon2id-derived keys.

**Trust assumption**: Server-side storage is trusted for availability but not for confidentiality of message content (the server never holds plaintext). Client-side storage is encrypted at rest; the encryption key is derived from the user's password via Argon2id.

### B4: Client to Client (via MLS)

Clients share MLS group state through the server. Each client maintains its own MLS group state machine and validates all incoming MLS messages (signature verification, epoch checks). The MLS ratchet tree is embedded in Welcome messages (`use_ratchet_tree_extension = true`).

**Trust assumption**: Each client trusts only its own MLS state and verifies all protocol messages. A malicious client cannot decrypt messages from groups it has not been invited to.

## Assets

| Asset | Sensitivity | Storage Location |
|-------|-------------|------------------|
| Message plaintext | Critical | Client memory only (never on server) |
| Ed25519 identity keypair (seed) | Critical | Client disk (SQLCipher), zeroized in memory |
| MLS group epoch secrets | Critical | Client key store (DiskKeyStore), zeroized on drop |
| Hybrid KEM private keys | Critical | Client key store, zeroized via `Zeroizing<Vec<u8>>` |
| OPAQUE password file (server record) | High | Server SQLite (no plaintext password) |
| Session tokens | High | Server memory (DashMap), time-bounded expiry |
| Recovery codes | High | Shown once to user; encrypted bundles on server |
| Key Transparency Merkle log | Medium | Server (append-only, publicly auditable) |
| Group membership metadata | Medium | Server (group IDs, member fingerprints) |
| Message timing/size metadata | Medium | Server (observable during relay) |
| User identity public keys | Low | Server, Key Transparency log |

## Threat Actors

### TA1: Passive Network Observer

**Capability**: Can observe all network traffic between clients and server (or between federation peers). Cannot modify traffic (TLS prevents tampering).

**Goal**: Learn message content, communication patterns, or group membership.

### TA2: Compromised Server

**Capability**: Full control of the server process, including storage, OPAQUE state, and message routing. Can read all server-side data, modify routing behavior, and forge server-signed artifacts.

**Goal**: Read message content, impersonate users, or disrupt service.

### TA3: Compromised Client

**Capability**: Full access to one client's local state, including identity keys, MLS group state, and decrypted messages. May be an insider who was legitimately added to a group.

**Goal**: Access messages from groups they were removed from, impersonate the compromised user, or exfiltrate keys for future decryption.

### TA4: Malicious Group Member

**Capability**: A legitimate group member who acts adversarially within the MLS protocol. Can send messages, propose updates, and attempt protocol deviations.

**Goal**: Impersonate other members, forge message history, prevent key rotation, or silently add unauthorized members.

### TA5: Quantum Adversary (Harvest Now, Decrypt Later)

**Capability**: Can record all current network traffic and will have access to a cryptographically-relevant quantum computer in the future.

**Goal**: Decrypt recorded traffic to recover message content or long-term keys.

## Threats and Mitigations

### T1: Message Confidentiality

**Threat**: An attacker intercepts encrypted messages and attempts to recover plaintext.

**Mitigations**:
- MLS (RFC 9420) provides end-to-end encryption; the server only sees opaque `MLSMessage` blobs.
- The delivery service is MLS-unaware (ADR-004): it routes blobs by `group_id` without inspecting content.
- Application messages are padded to fixed bucket sizes (256, 1024, 4096, 16384 bytes) before MLS encryption, hiding actual message length from the server.
- Sealed sender envelopes embed the sender identity inside the encrypted payload, so the server cannot determine which group member sent a message.

### T2: Message Integrity and Authenticity

**Threat**: An attacker modifies messages in transit or forges messages from another user.

**Mitigations**:
- MLS Commit messages are signed with Ed25519 by the sender's identity key.
- Sealed sender envelopes include an Ed25519 signature over `magic || sender_key || payload`, verified by recipients.
- QUIC + TLS 1.3 provides transport-level integrity (AEAD).
- The Key Transparency Merkle log binds (username, identity_key) pairs; clients can audit the log to detect key substitution attacks.

### T3: Authentication Bypass

**Threat**: An attacker registers with a stolen identity or logs in without valid credentials.

**Mitigations**:
- Authentication uses OPAQUE (RFC 9497) with Ristretto255 and Argon2id KSF. The server never sees the plaintext password.
- Session tokens have time-bounded expiry; expired sessions are cleaned up on validation.
- OPAQUE's triple-DH key exchange provides mutual authentication and resistance to pre-computation attacks.

### T4: Key Compromise and Forward Secrecy

**Threat**: Compromise of a long-term key allows decryption of past messages.

**Mitigations**:
- MLS provides forward secrecy via epoch rotation. Each Commit advances the group epoch and derives fresh encryption keys. Compromise of current keys does not reveal past epoch keys.
- MLS provides post-compromise security: a self-update (key rotation) proposal, once committed, re-derives all group secrets, healing from a key compromise.
- KeyPackages are single-use (ADR-005): each KeyPackage is consumed on fetch, preserving forward secrecy of the initial key exchange.

### T5: Metadata Privacy

**Threat**: The server learns communication patterns (who talks to whom, when, and how much) even without reading message content.

**Mitigations**:
- Sealed sender hides the sender identity from the server within group messages.
- Message padding (uniform boundary, default 256 bytes) reduces size-based traffic analysis.
- Traffic resistance mode: the server injects decoy messages at a configurable rate, adds random timing jitter before responses, and pads all payloads uniformly. Decoy messages are indistinguishable from real messages on the wire; recipients discard them by unpadding to an empty payload.
- Decoy generation uses `generate_decoy()` which produces cryptographically random padding.

**Residual risk**: Group IDs and recipient identity key fingerprints are visible to the server for routing. IP addresses are visible at the transport layer.

### T6: Post-Quantum Threats

**Threat**: A quantum adversary records current traffic and later uses a quantum computer to break classical key exchange.

**Mitigations**:
- MLS HPKE operations use a hybrid KEM: X25519 + ML-KEM-768 (FIPS 203). The shared secret is derived as `HKDF-SHA256(X25519_ss || ML-KEM_ss, info="quicnprotochat-hybrid-v1")`.
- The hybrid construction follows the combiner approach from draft-ietf-tls-hybrid-design. Security degrades gracefully: if either component is broken, the other still provides protection.
- The `HybridCryptoProvider` integrates with OpenMLS, producing hybrid (1216-byte public, 2432-byte private) init keys in KeyPackages.
- A post-quantum Noise handshake (`pq_noise` module) mixes ML-KEM-768 shared secrets into the Noise_XX chaining key, providing PQ-protected transport when enabled.

**Residual risk**: The classical Noise_XX handshake (when `pq_noise` is not enabled) uses X25519 only. This is an accepted residual risk (ADR-006) — no long-lived content secrets transit the Noise handshake.

### T7: Replay Attacks

**Threat**: An attacker replays a previously observed message to cause duplicate delivery or state confusion.

**Mitigations**:
- MLS epochs provide implicit replay protection: messages from a previous epoch are rejected by the receiver (`receive_stale_epoch_message_returns_error` test).
- MLS sequence numbers within an epoch detect duplicate or out-of-order application messages.
- The PQ Noise transport uses monotonic nonce counters; replaying a ciphertext at the wrong nonce causes decryption failure.
- QUIC itself provides transport-level replay protection.

### T8: Key Transparency Attacks

**Threat**: The server silently replaces a user's identity key to perform a man-in-the-middle attack.

**Mitigations**:
- The Key Transparency Merkle log uses SHA-256 hash chains with RFC 6962 domain-separation prefixes (`0x00` for leaves, `0x01` for internal nodes) to prevent second-preimage attacks.
- Leaf hashes commit to both username and identity key: `SHA-256(0x00 || SHA-256(username || 0x00 || identity_key))`.
- Clients can request inclusion proofs and verify them against a known root hash.
- A key revocation log records revocation entries with reason codes, preventing revoked keys from being reused.
- Safety numbers (Signal-style, 60-digit) allow users to verify identity keys out-of-band.

### T9: Account Recovery Attacks

**Threat**: An attacker obtains recovery codes and recovers a victim's identity.

**Mitigations**:
- Recovery codes are 8 alphanumeric strings of 6 characters each, generated from OS CSPRNG.
- Each code derives an encryption key via Argon2id (19 MiB memory, 2 iterations) before decrypting the recovery bundle (ChaCha20-Poly1305).
- The server stores only encrypted bundles keyed by `SHA-256(SHA-256("qpc-recovery-token:" || code))` -- it never sees plaintext codes.
- Recovery code validation uses constant-time comparison (`constant_time_eq`).
- Bundle size is capped at 64 KiB to prevent resource exhaustion.

### T10: Denial of Service

**Threat**: An attacker floods the server with requests to prevent legitimate users from communicating.

**Mitigations**:
- Tower middleware provides rate limiting per client.
- RPC framing enforces a maximum payload size of 4 MiB.
- Session token validation is O(1) via DashMap.

## Out of Scope

The following are explicitly out of scope for a security audit of quicprochat:

- **User interface code** (TUI, CLI argument parsing) -- not security-sensitive
- **Build system and CI** (Dockerfiles, justfile, GitHub Actions)
- **Documentation** (mdBook, README)
- **SDK bindings** (Go, Python, TypeScript, WASM, FFI) -- thin wrappers over the Rust SDK
- **Performance optimization** -- not a security concern unless it introduces side channels

## Known Limitations

1. **Client reconnection**: There is currently no automatic reconnection logic. A disconnected client must re-authenticate and re-join groups manually. This is a reliability concern, not a security concern.

2. **In-flight RPC tracking**: The client does not track in-flight RPCs for timeout/retry. Lost messages during network interruption are not automatically retransmitted.

3. **Classical Noise transport**: When the `pq_noise` feature is not enabled, the QUIC + TLS 1.3 transport uses classical cryptography only (X25519 for key exchange). This is an accepted residual risk (ADR-006) as the content layer is PQ-protected via MLS hybrid KEM.

4. **Server-side metadata**: The server necessarily observes group IDs, recipient fingerprints, message sizes (before MLS encryption, after padding), and timing of messages. Traffic resistance mitigates but does not eliminate this.

5. **No server-side message expiration**: The offline message queue does not currently enforce a maximum retention period. Messages queue indefinitely until consumed.

6. **OPAQUE registration not rate-limited**: Registration endpoints should be rate-limited to prevent mass account creation. The rate limiter covers authenticated endpoints but registration-time rate limiting is not yet enforced.
