Skip to content

A control frame's signed payload states no freshness, so a captured one verifies forever #403

Description

@bahdotsh

Split out of the review of #399, where the leaf crate bounds the symptom and cannot close the cause.

The gap

The canonical control-frame signing payload (control_signing_payload in offline-protocol-sealed) is built from the sender, the id, the recipient and the content. It states who, to whom, and what. It states nothing about when, so a frame captured off the air verifies exactly as well on its tenth delivery as on its first.

The destructive case is a key package carrying session_reset, which tears a live session down. Anyone who records one has a repeatable way to break a pair.

What is in place, and what it is not

offline-protocol-leaf remembers the ids of the last few reset frames it acted on, so the same frame cannot spend twice. That bounds a repeat. It does not close replay: an attacker holding a reset frame older than that ring can still spend it once, and the ring is per-peer and bounded because the device it runs on has a few hundred kilobytes of flash.

The phone has no equivalent memory at all.

What closing it needs

A freshness field inside the signed payload: a timestamp the verifier bounds, a counter it tracks, or a nonce it has to have issued. Each is a change to the wire and to both ends, and each has to survive a leaf whose clock is only as good as its last pairing. That is why it is not a device-side patch.

Recorded as an open gap in the reset section of docs/spec/leaf-provisioning.md. Sibling of #396 (unbounded key package lifetimes admitted on import), which came out of the same stage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions