mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Forward-merge of the docs-overhaul squash (5abf9a9) and top-level README rewrite (18019bb). Conflict resolution: - README.md: master's rewritten feature lists adopted, with the encryption bullets reflecting next's two-layer Noise XX (replacing the IK/XK pair master describes for v0.3.0). - 6 design/reference markdown files (fips-bloom-filters.md, fips-mesh-layer.md, fips-mesh-operation.md, fips-session-layer.md, fips-transport-layer.md, reference/wire-formats.md): master's reorg taken, next's protocol details preserved (XX handshake naming, bloom v2 RLE/delta wire format, v2 LookupRequest sizing). - fips-intro.md modify/delete: accepted master's split into fips-architecture.md / fips-concepts.md / fips-prior-work.md, then re-applied next's IK/XK -> XX transition and spin-bit removal across the relevant split files. Same pass swept docs/reference/security.md, docs/design/fips-mmp.md, docs/design/fips-security.md, docs/design/fips-nostr-discovery.md, docs/design/port-advertisement-and-nat-traversal.md, docs/how-to/enable-nostr-discovery.md, and the affected tutorials so no IK/XK or spin-bit prose remains in current-state docs. - Diagram path conflicts: noise-ik-msg{1,2}.svg removed (IK is gone); noise-xx-msg{1,2,3}.svg moved from docs/design/diagrams/ to docs/reference/diagrams/ to match master's diagram reorg. The wire-formats.md image references resolve correctly to the new path. Local verification: cargo build --release, cargo test (1265 passed, 4 ignored), cargo clippy -D warnings, cargo fmt --check all green.
536 lines
24 KiB
Markdown
536 lines
24 KiB
Markdown
# FIPS Session Protocol (FSP)
|
|
|
|
The FIPS Session Protocol is the topmost layer of the FIPS protocol stack.
|
|
It sits above the FIPS Mesh Protocol (FMP) and below applications (native
|
|
FIPS API or IPv6 adapter). FSP provides end-to-end authenticated, encrypted
|
|
datagram delivery between any two FIPS nodes, regardless of how many
|
|
intermediate hops separate them.
|
|
|
|
## Role
|
|
|
|
FSP manages end-to-end communication sessions between FIPS nodes identified by
|
|
their public keys (npubs). Each session provides:
|
|
|
|
- **End-to-end encryption**: Payload confidentiality independent of how many
|
|
intermediate nodes handle the traffic
|
|
- **Mutual authentication**: Both parties prove they control the private key
|
|
for their claimed identity
|
|
- **Replay protection**: Counter-based nonces with sliding window, tolerant of
|
|
UDP packet loss and reordering
|
|
- **Transport independence**: Sessions survive transport changes, route
|
|
changes, and address changes — they are bound to npub identities, not to
|
|
transport paths
|
|
|
|
FSP is a datagram session protocol. It provides encrypted datagrams, not
|
|
reliable streams. There is no FIPS equivalent of TCP; if applications need
|
|
reliability, ordering, or flow control, they provide it themselves (typically
|
|
by running TCP over the FIPS IPv6 adapter).
|
|
|
|
## Services Provided to Applications
|
|
|
|
Applications access the FIPS mesh through two interfaces, both served by FSP:
|
|
|
|
### Native FIPS API
|
|
|
|
Applications address destinations directly by npub or public key. The FIPS
|
|
stack resolves the destination's node_addr, establishes or reuses a session,
|
|
encrypts the payload, and routes through FMP. No DNS involvement.
|
|
|
|
### IPv6 Adapter
|
|
|
|
Unmodified IPv6 applications use a TUN device with `fd00::/8` routing. A local
|
|
DNS service maps npub → IPv6 address and primes the identity cache. Packets
|
|
arriving at the TUN are translated to FIPS datagrams and routed through FSP.
|
|
|
|
See [fips-ipv6-adapter.md](fips-ipv6-adapter.md) for the IPv6 adaptation
|
|
layer.
|
|
|
|
### Port-Based Service Dispatch
|
|
|
|
FSP DataPackets carry a 4-byte port header (source and destination port) inside
|
|
the AEAD envelope, enabling multiple services to share a single session. The
|
|
IPv6 adapter runs on port 256; the native FIPS API and future services
|
|
(gateways, application protocols) register on other ports. Port dispatch is
|
|
internal to the FSP layer — services see only their payload, not the port
|
|
header.
|
|
|
|
### What Applications Get
|
|
|
|
- **Authenticated datagram delivery**: Each datagram is encrypted and
|
|
authenticated with session keys bound to both parties' npubs
|
|
- **Session transparency**: Sessions are established on demand and maintained
|
|
automatically. Applications send packets; FSP handles session setup,
|
|
encryption, and teardown.
|
|
- **Endpoint identity**: Applications address destinations by npub. The FIPS
|
|
address is the public key.
|
|
|
|
### What Applications Do Not Get
|
|
|
|
- **Reliability**: Datagrams may be lost, duplicated, or delivered out of
|
|
order. FSP provides no retransmission or ordering.
|
|
- **Path MTU discovery**: FSP does not signal MTU to applications. The IPv6
|
|
adapter handles MTU enforcement via ICMP Packet Too Big and TCP MSS
|
|
clamping.
|
|
- **Congestion control**: FSP does not throttle traffic. Applications running
|
|
TCP over IPv6 get TCP's congestion control; native API applications must
|
|
manage their own sending rate.
|
|
|
|
## Services Required from FMP
|
|
|
|
FSP treats FMP as a black box providing three services. FSP knows nothing about
|
|
transports, transport addresses, links, peers, spanning trees, coordinates,
|
|
bloom filters, hop counts, or network topology.
|
|
|
|
### SessionDatagram Forwarding
|
|
|
|
FMP accepts a SessionDatagram (source node_addr, destination node_addr, TTL,
|
|
path MTU, payload) and delivers it best-effort toward the destination. Delivery
|
|
may traverse multiple hops, each with independent link encryption.
|
|
|
|
### Error Signaling
|
|
|
|
FMP signals routing failures asynchronously:
|
|
|
|
- **CoordsRequired**: A transit node lacks the destination's tree coordinates.
|
|
FSP responds by sending a standalone CoordsWarmup (0x14) message
|
|
(rate-limited), re-initiating discovery, and resetting the coordinate warmup
|
|
counter.
|
|
- **PathBroken**: Greedy routing reached a dead end. FSP responds by sending
|
|
a standalone CoordsWarmup (rate-limited), re-discovering the destination's
|
|
current coordinates, and resetting the warmup counter.
|
|
- **MtuExceeded**: A transit node cannot forward a SessionDatagram because
|
|
the packet exceeds the next-hop link MTU; FSP adjusts its
|
|
session-layer path MTU estimate from the reported bottleneck. See
|
|
[fips-mtu.md](fips-mtu.md) for the full forward/reverse MTU model.
|
|
|
|
All three signals are generated by transit nodes (not the destination) and
|
|
travel back to the source inside a new SessionDatagram. They are plaintext
|
|
(not end-to-end encrypted) because transit nodes have no session with the
|
|
source.
|
|
|
|
### Local Delivery
|
|
|
|
When a SessionDatagram arrives with a destination node_addr matching the local
|
|
node, FMP delivers it to FSP for session-layer processing.
|
|
|
|
## Session Lifecycle
|
|
|
|
### Session Establishment
|
|
|
|
Sessions are established on demand when the first datagram needs to be sent to
|
|
a destination with no existing session.
|
|
|
|
FSP uses Noise XX for session key agreement (Noise Protocol Framework;
|
|
Perrin 2018). Neither side requires prior knowledge of the other's
|
|
static key — both identities are revealed during the handshake
|
|
(responder in msg2, initiator in msg3). An optional protocol negotiation
|
|
payload may be appended to msg2/msg3 (omitted for rekey handshakes).
|
|
|
|
The handshake is a three-message flow carried in SessionSetup, SessionAck,
|
|
and SessionMsg3:
|
|
|
|
1. **Initiator** sends SessionSetup containing Noise XX msg1 (ephemeral key
|
|
only) and both parties' tree coordinates
|
|
2. **Responder** processes msg1, sends SessionAck containing Noise XX msg2
|
|
(ephemeral key + encrypted static key + encrypted epoch) and both
|
|
parties' tree coordinates. The responder transitions to AwaitingMsg3
|
|
state.
|
|
3. **Initiator** processes msg2 (learning the responder's identity), sends
|
|
SessionMsg3 containing its encrypted static key and encrypted epoch.
|
|
The responder learns the initiator's identity from msg3. Both parties
|
|
derive identical symmetric session keys and the session is established.
|
|
|
|
Post-handshake identity verification uses x-only key comparison
|
|
(parity-independent) to confirm the revealed identity matches the
|
|
expected npub.
|
|
|
|
Each side's epoch (an 8-byte random value generated at startup) is
|
|
exchanged encrypted in msg2 and msg3. On subsequent handshakes, an epoch
|
|
mismatch indicates the peer has restarted, triggering session
|
|
re-establishment — similar to IKEv2's INITIAL_CONTACT notification for
|
|
peer restart detection (RFC 7296 §2.4).
|
|
|
|
Packets that trigger session establishment are queued (with bounded buffer)
|
|
and transmitted after the session is established.
|
|
|
|
### Self-Bootstrapping
|
|
|
|
SessionSetup is self-bootstrapping for routing. It carries the source's and
|
|
destination's tree coordinates in the clear (not inside the Noise payload).
|
|
As the message transits intermediate nodes, each node caches these coordinates,
|
|
warming the path for subsequent data packets that carry only addresses (no
|
|
coordinates).
|
|
|
|
SessionAck carries both the responder's and initiator's coordinates back
|
|
along the reverse path, warming caches in the other direction. This ensures
|
|
return-path transit nodes can route even when the reverse path diverges from
|
|
the forward path (e.g., after tree reconvergence).
|
|
|
|
### Simultaneous Initiation
|
|
|
|
When both nodes attempt to establish a session simultaneously ("crossing
|
|
hellos"), a deterministic tie-breaker resolves the conflict, mirroring
|
|
IKEv2's simultaneous initiation resolution (RFC 7296 §2.8):
|
|
|
|
- If `local_node_addr < remote_node_addr`: Continue as initiator, ignore
|
|
incoming setup
|
|
- If `local_node_addr > remote_node_addr`: Abort own initiation, switch to
|
|
responder role
|
|
|
|
This lowest-address-wins approach ensures exactly one handshake completes.
|
|
|
|
### Data Transfer
|
|
|
|
Once established, sessions carry encrypted data using the FSP pipeline. Each
|
|
encrypted message includes:
|
|
|
|
- A 12-byte cleartext header (used as AEAD AAD) containing the counter and
|
|
flags (including the CP flag for coordinate cache warming)
|
|
- Optional cleartext coordinates when the CP flag is set
|
|
- An AEAD-encrypted payload containing a 6-byte inner header (session-relative
|
|
timestamp, message type, inner flags) followed by DataPacket content: a 4-byte
|
|
port header (src_port, dst_port) and the service payload. The receiver
|
|
dispatches by destination port to the registered service handler.
|
|
|
|
### Session Idle Timeout
|
|
|
|
Sessions that see no traffic for a configurable duration (default 90s) are
|
|
torn down. When traffic resumes, a new session is established automatically.
|
|
|
|
Only DataPacket (message type 0x10) send/receive and session establishment
|
|
reset `last_activity`. MMP traffic — SenderReport, ReceiverReport, and
|
|
PathMtuNotification — does not reset the idle timer. This means a session
|
|
carrying only MMP reports and no application data will still tear down after
|
|
`node.session.idle_timeout_secs`. MMP reports continue flowing until the
|
|
session is torn down, providing final measurement data for the teardown log.
|
|
|
|
The idle timeout is deliberately shorter than the coordinate cache TTL (300s).
|
|
This ordering ensures that when traffic stops and the session tears down, the
|
|
transit node coordinate caches are still warm when a new session is established.
|
|
The fresh SessionSetup re-warms the caches, maintaining routing continuity.
|
|
|
|
### Session Independence from Transport
|
|
|
|
Sessions exist above the routing layer and are bound to npub identities, not
|
|
transport addresses or routing paths — following WireGuard's approach
|
|
(Donenfeld 2017) of binding cryptographic sessions to identity keys rather
|
|
than network addresses. A session survives:
|
|
|
|
- Transport failover (UDP → Ethernet → back to UDP)
|
|
- Route changes (different intermediate hops)
|
|
- Transport address changes (IP address or port changes)
|
|
- Topology changes (direct peer becomes multi-hop or vice versa)
|
|
|
|
## End-to-End Encryption
|
|
|
|
### Noise XX Pattern
|
|
|
|
FSP uses the same Noise XX pattern as the link layer (FMP). The full
|
|
Noise descriptor is `Noise_XX_secp256k1_ChaChaPoly_SHA256`.
|
|
|
|
The XX pattern (no pre-message):
|
|
|
|
- **msg1** (`→ e`): Initiator sends ephemeral key only. No identity
|
|
disclosed, no DH with static keys.
|
|
- **msg2** (`← e, ee, s, es`): Responder sends ephemeral key, encrypted
|
|
static key, and encrypted epoch. The initiator learns the responder's
|
|
identity.
|
|
- **msg3** (`→ s, se`): Initiator sends encrypted static key and encrypted
|
|
epoch. The responder learns the initiator's identity. Both parties now
|
|
share identical session keys.
|
|
|
|
After the handshake, Noise produces two directional symmetric keys
|
|
(`send_key`, `recv_key`) used with ChaCha20-Poly1305 for all subsequent
|
|
data.
|
|
|
|
XX requires no prior knowledge of the peer's static key. The initiator
|
|
still needs the destination's npub to address the SessionSetup, but the
|
|
Noise handshake itself does not depend on it — identity is verified
|
|
post-handshake by comparing the revealed key against the expected npub.
|
|
|
|
### Cryptographic Primitives
|
|
|
|
FSP uses ChaCha20-Poly1305 with secp256k1 ECDH; see
|
|
[../reference/security.md](../reference/security.md) for the full
|
|
primitive table shared with the link layer.
|
|
|
|
### secp256k1 Parity Normalization
|
|
|
|
Nostr npubs encode x-only public keys (32 bytes, no y-coordinate parity).
|
|
When the Noise XX handshake reveals a peer's static key via
|
|
`public_key().serialize()`, the key has its actual parity (0x02 or 0x03
|
|
prefix). The default secp256k1 ECDH hash also includes a parity-dependent
|
|
version byte.
|
|
|
|
Both operations are normalized to be parity-independent: ECDH hashes only
|
|
the x-coordinate of the result point, and post-handshake identity
|
|
verification uses `x_only_public_key()` to strip parity before comparing
|
|
against the expected npub. This ensures handshakes and identity checks
|
|
succeed regardless of key parity.
|
|
|
|
### Privacy Note
|
|
|
|
Noise XX provides mutual identity protection — both the initiator's and
|
|
responder's static keys are encrypted under the evolving shared secret
|
|
(derived from DH operations completed in earlier messages). An attacker
|
|
who compromises only one side's nsec cannot decrypt the other side's
|
|
identity from captured handshake messages without also obtaining the
|
|
corresponding ephemeral key. Since session-layer traffic traverses
|
|
untrusted intermediate nodes, this mutual identity hiding is valuable.
|
|
|
|
### Data Packet Authentication
|
|
|
|
FSP uses AEAD authentication only — no per-packet signatures. The Noise
|
|
handshake binds session keys to both parties' static keys, so only holders of
|
|
the corresponding nsecs can derive the session keys. This provides implicit
|
|
authentication for every packet, matching WireGuard and Lightning's approach.
|
|
|
|
### Forward Secrecy
|
|
|
|
Ephemeral keys in the Noise handshake provide forward secrecy — a standard
|
|
property of Noise handshake patterns that include ephemeral key exchange.
|
|
Compromise of static keys (nsec) does not reveal past session keys, because
|
|
session keys are derived in part from ephemeral-ephemeral DH (`ee`), and
|
|
ephemeral keys are discarded after the handshake.
|
|
|
|
## Replay Protection
|
|
|
|
FSP uses explicit 8-byte counters on the wire for replay protection, adapted
|
|
from the DTLS anti-replay mechanism (Rescorla & Modadugu, RFC 6347). Each side
|
|
maintains a monotonically increasing send counter, included in the 12-byte
|
|
cleartext header of every encrypted message. The receiver maintains a sliding
|
|
window (2048-entry bitmap) tracking which counters have been seen.
|
|
|
|
This design is critical for operation over unreliable transports. Under UDP
|
|
packet loss or reordering, implicit nonce counters (where the receiver
|
|
increments on each decrypt attempt) would desynchronize permanently — a failed
|
|
`decrypt()` increments the nonce, and the desync grows with each lost packet.
|
|
Explicit counters with a sliding bitmap window — the standard DTLS approach —
|
|
allow the receiver to decrypt any packet independently, regardless of what
|
|
packets were lost or reordered.
|
|
|
|
The same `ReplayWindow` and `decrypt_with_replay_check()` implementation is
|
|
used at both the link and session layers.
|
|
|
|
## Hybrid Coordinate Warmup Strategy
|
|
|
|
Session establishment (SessionSetup/SessionAck) warms transit node coordinate
|
|
caches along the path. But coordinate caches have a finite TTL (default 300s),
|
|
and entries may be evicted under memory pressure. When a transit node's cache
|
|
entry expires, it cannot forward data packets (which carry only addresses, not
|
|
coordinates) and sends a CoordsRequired error.
|
|
|
|
FSP uses a hybrid warmup strategy combining proactive piggybacking with
|
|
reactive standalone messages to keep transit caches populated (Yggdrasil
|
|
uses a similar approach of embedding coordinates in session traffic to
|
|
warm transit node caches):
|
|
|
|
### Proactive Warmup Phase
|
|
|
|
After session establishment, the first N data packets (configurable, default 5)
|
|
per session attempt to piggyback source and destination coordinates via the CP
|
|
flag in the FSP common prefix. The coordinates appear in cleartext between the
|
|
12-byte header and the ciphertext, allowing transit nodes to cache them without
|
|
decryption.
|
|
|
|
If piggybacking coordinates would cause the total packet to exceed the
|
|
transport MTU, the source sends a standalone **CoordsWarmup** message (0x14)
|
|
first, followed by the data packet without the CP flag. This ensures transit
|
|
caches are warmed even when data packets are near the MTU limit.
|
|
|
|
### CoordsWarmup Message (0x14)
|
|
|
|
CoordsWarmup is an encrypted FSP message (phase 0x0) with the CP flag set and
|
|
inner msg_type 0x14. It carries cleartext source and destination coordinates
|
|
between the FSP header and the AEAD ciphertext, using the same format as
|
|
CP-flagged data packets. The inner body is empty — the message exists solely
|
|
to deliver coordinates to transit nodes.
|
|
|
|
Transit nodes extract coordinates via the existing `try_warm_coord_cache()`
|
|
code path with zero changes to the transit forwarding logic. CoordsWarmup is
|
|
indistinguishable from any other CP-flagged message at the transit layer.
|
|
|
|
On the wire, a CoordsWarmup message consists of the standard 12-byte FSP
|
|
header (used as AEAD AAD) with ver=0, phase=0, flags=CP, followed by
|
|
cleartext source and destination coordinates (same encoding as any
|
|
CP-flagged packet), followed by 22 bytes of AEAD ciphertext (6-byte inner
|
|
header and 16-byte Poly1305 tag). The total FSP payload is 12 bytes of
|
|
header, the coordinate data, and 22 bytes of ciphertext.
|
|
|
|
### Steady State
|
|
|
|
After the warmup count is reached, FSP clears the CP flag and sends minimal
|
|
data packets (12-byte header + ciphertext). Transit nodes serve from their
|
|
coordinate caches.
|
|
|
|
### Reactive Re-Warm
|
|
|
|
When FSP receives a CoordsRequired or PathBroken signal:
|
|
|
|
1. A standalone CoordsWarmup message is sent immediately to re-warm transit
|
|
caches, rate-limited at one per destination per configurable interval
|
|
(default 2000ms, `node.session.coords_response_interval_ms`)
|
|
2. The warmup counter resets — subsequent data packets piggyback coordinates
|
|
again when possible (or send additional CoordsWarmup messages when the
|
|
data packet would exceed the MTU)
|
|
3. A new LookupRequest may be initiated to rediscover the destination's
|
|
current coordinates (always for PathBroken; optionally for CoordsRequired)
|
|
4. When the LookupResponse arrives for an established session, the warmup
|
|
counter resets again (handling the timing gap where warmup packets might
|
|
fire before transit caches are repopulated by discovery)
|
|
|
|
The source-side rate limiting prevents amplification: at most one standalone
|
|
CoordsWarmup response per destination per `coords_response_interval_ms`
|
|
(default 2s). This is independent of the transit-node rate limiting on error
|
|
signal generation (100ms per destination).
|
|
|
|
### Warmup State Machine
|
|
|
|

|
|
|
|
## Identity Cache
|
|
|
|
The IPv6 adapter requires an identity cache to map `fd00::/8` addresses
|
|
back to `(NodeAddr, PublicKey)` for routing; see
|
|
[fips-ipv6-adapter.md](fips-ipv6-adapter.md#identity-cache) for the
|
|
cache rationale, eviction policy, and population mechanics.
|
|
|
|
## Coordinate Cache
|
|
|
|
The coordinate cache maps `NodeAddr → TreeCoordinate` and is the critical
|
|
data structure that enables efficient multi-hop routing. Without cached
|
|
coordinates for a destination, FMP cannot make forwarding decisions and must
|
|
either fall back to bloom-filter-only routing or signal CoordsRequired.
|
|
|
|
### Unified Cache
|
|
|
|
The coordinate cache is a single unified cache (merged from previously
|
|
separate coord_cache and route_cache). All coordinate sources — SessionSetup
|
|
transit, CP-flagged data packets, LookupResponse — write to the same cache.
|
|
|
|
### Eviction Policy
|
|
|
|
- **TTL-based expiration**: Entries expire after a configurable duration
|
|
(default 300s)
|
|
- **Refresh on use**: Active routing through a cache entry resets its TTL,
|
|
keeping hot entries alive
|
|
- **LRU eviction**: When the cache is full, least recently used entries are
|
|
evicted first
|
|
- **Flush on parent change**: When the local node's tree parent changes, the
|
|
entire coordinate cache is flushed. Tree parent changes mean the node's own
|
|
coordinates have changed, making cached coordinates for other nodes
|
|
potentially stale for routing purposes.
|
|
|
|
### Timer Ordering
|
|
|
|
Cache and session timers are ordered so that idle sessions tear down before
|
|
transit caches expire:
|
|
|
|
| Timer | Default | Purpose |
|
|
| ----- | ------- | ------- |
|
|
| Session idle timeout | 90s | Tear down unused sessions |
|
|
| Coordinate cache TTL | 300s | Expire stale coordinates |
|
|
| DNS TTL | 300s | Expire DNS resolutions |
|
|
|
|
When traffic stops: the session tears down at 90s. When traffic resumes: DNS
|
|
re-resolves the identity, a fresh SessionSetup carries coordinates, and transit
|
|
node caches (still within their 300s TTL) are re-warmed.
|
|
|
|
## Session-Layer MMP
|
|
|
|
FSP runs an MMP instance per established session for end-to-end metrics
|
|
independent of hop count. Reports are encrypted and forwarded through
|
|
every transit link, so bandwidth cost is proportional to path length;
|
|
the session-layer report intervals are correspondingly higher than the
|
|
link-layer intervals (clamped to `[500ms, 10s]` vs. `[1s, 5s]`).
|
|
|
|
The session-layer instance shares its algorithms (SRTT, jitter, loss,
|
|
ETX) and report wire format with link-layer MMP. The differences —
|
|
configuration namespace (`node.session_mmp.*`), routing scope,
|
|
send-failure backoff, idle-timeout interaction, and the
|
|
PathMtuNotification mechanism — are documented in the unified MMP
|
|
treatment at [fips-mmp.md](fips-mmp.md). For the end-to-end path-MTU
|
|
echo specifically, see [fips-mtu.md](fips-mtu.md). Reports and
|
|
PathMtuNotification do **not** reset the session idle timer, so a
|
|
session carrying only MMP traffic still tears down at the configured
|
|
idle threshold.
|
|
|
|
### MtuExceeded Handling
|
|
|
|
When FMP signals MtuExceeded (a transit node could not forward a
|
|
SessionDatagram because it exceeded the next-hop link MTU), FSP uses
|
|
the reported bottleneck MTU to adjust its session-layer path MTU
|
|
estimate immediately. See [fips-mtu.md](fips-mtu.md) for the full
|
|
reactive PMTUD mechanism.
|
|
|
|
## Implementation Status
|
|
|
|
| Feature | Status |
|
|
| ------- | ------ |
|
|
| Session establishment (Noise XX) | **Implemented** |
|
|
| Peer restart detection (epoch exchange) | **Implemented** |
|
|
| MtuExceeded handling | **Implemented** |
|
|
| End-to-end encryption (ChaCha20-Poly1305) | **Implemented** |
|
|
| Explicit counter replay protection | **Implemented** |
|
|
| Hybrid coordinate warmup (CP + CoordsWarmup) | **Implemented** |
|
|
| FSP wire format (prefix, AAD, inner header) | **Implemented** |
|
|
| Session-layer MMP (with send-failure backoff) | **Implemented** |
|
|
| Identity cache (LRU-only) | **Implemented** |
|
|
| Coordinate cache (unified, TTL + refresh) | **Implemented** |
|
|
| Session idle timeout | **Implemented** |
|
|
| CoordsRequired handling | **Implemented** |
|
|
| PathBroken handling | **Implemented** |
|
|
| Simultaneous initiation tie-breaker | **Implemented** |
|
|
| Flush coord cache on parent change | **Implemented** |
|
|
| Rekey | **Implemented** |
|
|
| Port-based service multiplexing | **Implemented** |
|
|
| IPv6 header compression (shim on port 256) | **Implemented** |
|
|
| Path MTU tracking (FMP SessionDatagram field) | **Implemented** |
|
|
| Path MTU notification (end-to-end echo) | **Implemented** |
|
|
|
|
## References
|
|
|
|
### FIPS Internal Documentation
|
|
|
|
- [fips-concepts.md](fips-concepts.md) — Protocol overview
|
|
- [fips-architecture.md](fips-architecture.md) — Layer architecture and
|
|
identity model
|
|
- [fips-mesh-layer.md](fips-mesh-layer.md) — FMP specification (below FSP)
|
|
- [fips-ipv6-adapter.md](fips-ipv6-adapter.md) — IPv6 adaptation layer
|
|
(above FSP)
|
|
- [fips-mesh-operation.md](fips-mesh-operation.md) — Routing, discovery,
|
|
and error recovery
|
|
- [fips-mmp.md](fips-mmp.md) — Metrics Measurement Protocol (link + session)
|
|
- [fips-mtu.md](fips-mtu.md) — Path MTU model (PathMtuNotification,
|
|
MtuExceeded, hysteresis)
|
|
- [fips-prior-work.md](fips-prior-work.md) — Noise XX, WireGuard,
|
|
DTLS replay window, IKEv2 simultaneous initiation, hybrid coordinate
|
|
warmup citations
|
|
- [../reference/wire-formats.md](../reference/wire-formats.md) — Wire
|
|
format reference for all session message types
|
|
- [../reference/security.md](../reference/security.md) — Cryptographic
|
|
primitives and rekey defaults
|
|
|
|
### External References
|
|
|
|
- Perrin, T. ["The Noise Protocol Framework"](https://noiseprotocol.org/noise.html).
|
|
Revision 34, 2018. *Framework for building crypto protocols using Diffie-Hellman
|
|
key agreement and AEAD ciphers. FSP uses the XX handshake pattern.*
|
|
|
|
- Donenfeld, J.A. ["WireGuard: Next Generation Kernel Network Tunnel"](https://www.wireguard.com/papers/wireguard.pdf).
|
|
NDSS 2017. *Transport-independent cryptographic sessions bound to identity keys
|
|
rather than network addresses; AEAD-only authentication model.*
|
|
|
|
- Rescorla, E., Modadugu, N. [RFC 6347](https://datatracker.ietf.org/doc/html/rfc6347):
|
|
"Datagram Transport Layer Security Version 1.2". 2012. *Explicit sequence numbers
|
|
with sliding bitmap window for replay protection over unreliable transports.*
|
|
|
|
- Kaufman, C., Hoffman, P., Nir, Y., Eronen, P., Kivinen, T.
|
|
[RFC 7296](https://datatracker.ietf.org/doc/html/rfc7296):
|
|
"Internet Key Exchange Protocol Version 2 (IKEv2)". 2014. *Simultaneous
|
|
initiation resolution (§2.8) and INITIAL_CONTACT peer restart detection (§2.4).*
|
|
|
|
- Mogul, J., Deering, S. [RFC 1191](https://datatracker.ietf.org/doc/html/rfc1191):
|
|
"Path MTU Discovery". 1990. *End-to-end path MTU discovery; FSP adapts this for
|
|
overlay networks using transit-node min() propagation.*
|