Skip to content

docs: diagnose MLS INVALID_CIPHERTEXT during 2-phone federated training (OFF-3247) - #584

Open
taayyohh wants to merge 1 commit into
mainfrom
mb/off-3247-mls-ciphertext-decrypt-diagnosis
Open

taayyohh wants to merge 1 commit into
mainfrom
mb/off-3247-mls-ciphertext-decrypt-diagnosis

Conversation

@taayyohh

Copy link
Copy Markdown
Contributor

Summary

Diagnosis-only PR. No code change. Attached scratch doc walks the
message_decryption_failed INVALID_CIPHERTEXT path from the receive side
back to the OpenMLS error chain, enumerates the five underlying variants
that today collapse to one opaque code at the app, and proposes four
follow-on fix shapes (ordered by risk) with a decision tree for the next
2-phone session.

Primary hypothesis

Tier 2 reseal (protocol/send.rs::reseal_resend_content) advances the
sender's MLS encryption ratchet one generation on every retry. In the
observed federated-training session the sender has many messages in
flight concurrently and almost nothing is ACKing (45 message_delivered
across ~45k message_retrying and ~9k message_failed). Each failed
delivery becomes 5 reseal retries, each burning one more generation. The
sender's generation spread trivially exceeds the receiver's
SENDER_RATCHET_OUT_OF_ORDER_TOLERANCE = 32, so late/reordered frames
surface at the receiver as
SecretTreeError::TooDistantInThePast, which the SDK wraps into
MlsError::Decryption and reports to the app as
code: INVALID_CIPHERTEXT. No group_epoch_fork_detected fires because
the epoch is still agreed.

That matches the shape of the real session: round 1 clean, round 2+
decays, iPhone -> Seeker (thin direction) stays up, Seeker -> iPhone
(gradient-chunk fan-out, heavy direction) collapses.

Secondary hypothesis (noted, not primary)

Welcome-wins race at session establishment also produces
INVALID_CIPHERTEXT without a group_epoch_fork_detected. Discarded as
primary because it would show up as a burst at round 1 setup, not as
round 2+ decay after a clean round 1.

Proposed fix shapes

See the "Proposed fix shape" section of the doc. In order:

  1. F1: carry OpenMLS error chain text through to the event's
    reason field (safe; library-constant strings only). Confirms which
    of the five variants is firing before committing to a fix.
  2. F2: raise SENDER_RATCHET_OUT_OF_ORDER_TOLERANCE (32 -> 128/256).
    Both sides have to agree, so one SDK bump.
  3. F3: track seal_epoch on OutboxReseal and skip reseal when the
    session epoch is unchanged. Replay verbatim when safe; receiver's
    dedup catches duplicate ids before OpenMLS sees them.
  4. F4: dedup message_decryption_failed at the IM-app TrainingModule
    listener (phone-side ticket, not SDK).

How to verify after a fix lands

Doc includes a grep key: specific OpenMLS error strings that would land
in the reason field once F1 lands, and which fix shape each one points
at.

Refs

Linear: https://linear.app/offlineprotocol/issue/OFF-3247

…raining

Diagnosis-only, no code change. The attached scratch doc walks the
`message_decryption_failed INVALID_CIPHERTEXT` path from receive back to
the OpenMLS error chain, enumerates the five variants that currently
collapse to one opaque code at the app, and proposes four follow-on
fix shapes (ordered by risk) with a decision tree for the next 2-phone
session.

Primary hypothesis: Tier 2 reseal advances the sender ratchet one
generation per retry, and under lossy BLE with many concurrent in-flight
frames the sender's generation spread exceeds the receiver's
`SENDER_RATCHET_OUT_OF_ORDER_TOLERANCE = 32` window, surfacing as
`SecretTreeError::TooDistantInThePast` wrapped into
`MlsError::Decryption` and reported as `INVALID_CIPHERTEXT`. No
`group_epoch_fork_detected` fires because the epoch is still agreed.

Refs: https://linear.app/offlineprotocol/issue/OFF-3247

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant