session: derive E2E receive key from the peer's real device (fixes garbled inbound audio)#4
Open
roshank8s wants to merge 1 commit into
Open
Conversation
NewMediaPipeline derived the receive-direction E2E-SRTP key from FormatE2ESrtpParticipantID(peerJID); FormatParticipantID forces a bare @lid to device :0, so when the peer streams from a non-zero device the recv keystream is wrong. The payload cipher is AES-CTR (length preserving) and the WARP MI tag is not verified, so a wrong key yields correct-length, high-entropy garbage with no decrypt error, which the MLow decoder renders as robotic inbound audio. Sending is unaffected: the send key uses our own device-qualified LID. Pick the peer's real device without new signaling: the WARP MI tag is HMAC-SHA1 over the packet keyed by the sender's per-participant E2E auth key, so the peer's device is the one whose derived recv key reproduces the tag. Derive a candidate key per device index and lock onto the MI-tag match on the first inbound packet. Verified on a live 1:1 call: inbound audio goes from garbled to clean; 0% packet loss and 0 decrypt failures before and after. Source of truth: https://github.com/JotaDev66/WaCalls
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Inbound 1:1 call audio decodes to garbled/robotic noise, while outbound audio is clean.
Root cause
NewMediaPipeline(session.go) derives the E2E-SRTP receive key fromrtp.FormatE2ESrtpParticipantID(peerJID), andutil.FormatParticipantIDforces a bare@lidto device:0. The peer, however, streams from its real (non-zero) device, so the AES-CTR keystream is wrong. Sending is unaffected because the send key uses our own already-device-qualified LID.The failure is silent: the payload cipher is AES-CTR (length-preserving) and the WARP MI tag is not verified, so a wrong key produces correct-length, high-entropy garbage with no decrypt error — which the (correct) MLow decoder renders as robotic audio.
Evidence (via
WithDiagnostics, on a live 1:1 call)media_keys_input: peer keyed at:0, self at a real non-zero device (:78).Cross-reference
JotaDev66/WaCalls(stable, byte-identical MLow decoder) gets clean inbound audio because it re-keys the receive direction from the peer's real device-qualified JID, not a hard-coded:0.Fix
Pick the peer's real device without new signaling plumbing: the WARP MI tag is HMAC-SHA1 over the packet keyed by the sender's per-participant E2E auth key (the same key
ProtectAudiosigns with), so the peer's device is the one whose derived recv key reproduces the tag.buildRecvKeyCandidatesderives a candidate recv key per device index (default:0first);selectRecvKeylocks onto the MI-tag match on the first inbound packet and falls back to the default after a bounded number of probes.Alternatively this could key off the peer's device-qualified JID from the
accept/ relay-participant list (WaCalls' approach) to avoid the candidate search — happy to switch if you'd prefer that shape.Testing
go build ./...,go vet ./..., and the existing session round-trip KATs (go test .) pass.The same recv-key derivation is present on
meowcaller-leg, so this applies there too.