Repository navigation
Make call encryption keys work: array shape + room-event transport - #32
Merged
Merged
Conversation
The io.element.call.encryption_keys wire format (MSC3401 / Element Call
/ FluffyChat) carries keys as an array of {index, key}, but
mx_call_key_content() emitted and mx_call_key_parse() read it as a
single object. Off the wire the Olm plaintext is parsed with
simplifyVector = FALSE, so keys arrived as a list of lists, $index was
NULL, and the parser dropped every real key event: a peer's audio
decrypted to silence (e2ee_state_changed MISSING_KEY) and our own key
reached no one. The tests encoded the same wrong object shape, so they
passed against it.
mx_call_key_content() now wraps the entry so it serializes as an array;
mx_call_key_parse() reads the array (tolerating a data frame or a lone
object) and returns one entry per key, so a single event can carry
several indices; mx_call_handle() applies each. Tests use a spec-shaped
event parsed with simplifyVector = FALSE, the exact shape that
regressed.
FluffyChat / matrix-dart-sdk distributes the call encryption key as an encrypted ROOM event with a top-level device_id, not a to-device event. mx_crypto_process_sync() dropped type and content from decrypted room events, so the key was unreachable even after it was decrypted, and mx_call_handle() only looked at to-device: the bot received the caller's audio but had no key and decoded silence. - mx_crypto_process_sync(): decrypted room-event records keep their inner type and content (additive; text consumers still read body). - mx_call_handle(): reads call keys from processed$events (room events in the call's room) as well as to_device. - mx_call_key_parse(): accepts the room-event shape (top-level device_id, room taken from the event) alongside the to-device shape. - mx_call_key_content(): superset carrying both device_id and member, so one object serves either transport. - mx_call_send_key(): also posts the key as an encrypted room event (guarded) so FluffyChat can decrypt the bot; mx_send_encrypted() gained an event_type argument.
A leftover title/description block from the previous edit attached to the internal helper, generating a stray man page and a roxygen undocumented-parameter warning.
mx_call_send_key posts our key as a room event; the homeserver echoes it back in our own sync, where mx_call_handle's processed$events scan picked it up and applied our own key to our own participant slot. Skip parsed entries whose identity is the call's own.
A peer can open several Olm sessions to us and reply on any of them. The single inbound slot per peer was overwritten by each new session, so a message on a replaced session failed to decrypt and was dropped silently (a FluffyChat call key arrived on a session the bot had replaced, leaving the caller's audio MISSING_KEY). olm_in now holds a list of inbound sessions per peer curve25519; mx_crypto_process_sync appends new inbound sessions rather than overwriting, and olm_receive tries them all plus the outbound session. Legacy single-session stores load unchanged. The 'cannot decrypt Olm to-device message' warning now reports the message type, how many sessions were tried, and the create_inbound error for a failed prekey, so a dropped message is diagnosable.
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.
Make MatrixRTC call encryption keys actually work, found during the first live FluffyChat↔bot call: the bot connected, subscribed to the caller's audio, received frames, but every frame was undecryptable (
e2ee_state_changed MISSING_KEY) because no peer key was ever applied.Two independent bugs, both in the call-key path:
1.
keysis an array, not an object. Theio.element.call.encryption_keyscontent carrieskeysas an array of{index, key}.mx_call_key_content()emitted it as a single object andmx_call_key_parse()read it as one; off the wire the Olm/megolm plaintext is parsed withsimplifyVector = FALSE, sokeysarrives as a list of lists,$indexis NULL, and every real key event was dropped. The tests encoded the same wrong shape, so they passed against it.2. FluffyChat sends the key as a room event, not to-device. matrix-dart-sdk distributes the call key as an encrypted room event with a top-level
device_id.mx_crypto_process_sync()flattened every decrypted room event to a text-message record, droppingtypeandcontent, so the key was unreachable even once decrypted; andmx_call_handle()only readto_device.Changes:
mx_call_key_content():keysserializes as an array; superset content carrying both top-leveldevice_id(FluffyChat) and thememberblock (Element Call), so one object serves either transport.mx_call_key_parse(): reads the array (toleratingsimplifyVector = FALSElist-of-lists, a data frame, and a lone object), accepts both the to-device shape (member.claimed_device_id, contentroom_id) and the room-event shape (top-leveldevice_id, room from the event); returns one entry per key.mx_crypto_process_sync(): decrypted room-event records keep their innertypeandcontent(additive; text consumers still readbody).mx_call_handle(): applies call keys fromprocessed$events(room events in the call's room) as well asto_device.mx_call_send_key(): also posts the key as an encrypted room event (guarded) so FluffyChat can decrypt the bot;mx_send_encrypted()gained anevent_typeargument.Tests: spec-shaped events parsed with
simplifyVector = FALSE(the exact regressed shape), to-device and room-event shapes, multi-key events, object tolerance, handle reading room-event keys, and a serialization check thatkeysis a JSON array. 935 pass. Version 0.2.1.2.