fix(voice): guard e2ee_manager access when E2EE disabled (diagnostic mode)

This commit is contained in:
Christian Gick
2026-02-22 13:46:51 +02:00
parent c188a2daf6
commit 190b35945c

View File

@@ -302,19 +302,23 @@ class VoiceSession:
# The caller's track is subscribed during the wait; if no key is set when # The caller's track is subscribed during the wait; if no key is set when
# the frame cryptor is first created it enters DEC_FAILED and drops all frames # the frame cryptor is first created it enters DEC_FAILED and drops all frames
# even after the key is set later. # even after the key is set later.
kp = self.lk_room.e2ee_manager.key_provider kp = None
kp.set_key(bot_identity, self._bot_key, 0) if e2ee_opts is not None:
logger.info("Set bot raw key for %s (%d bytes)", bot_identity, len(self._bot_key)) kp = self.lk_room.e2ee_manager.key_provider
# Caller keys: use set_shared_key with pre-derived AES (bypasses Rust HKDF). kp.set_key(bot_identity, self._bot_key, 0)
# Per-participant set_key is NOT called for caller — Rust HKDF may not match EC's JS HKDF. logger.info("Set bot raw key for %s (%d bytes)", bot_identity, len(self._bot_key))
if self._caller_all_keys: # Caller keys: use set_shared_key with pre-derived AES (bypasses Rust HKDF).
for idx, base_k in sorted(self._caller_all_keys.items()): # Per-participant set_key is NOT called for caller — Rust HKDF may not match EC's JS HKDF.
kp.set_shared_key(_hkdf_derive(base_k), idx) if self._caller_all_keys:
logger.info("Early-set shared_key (pre-derived) for caller indices %s", for idx, base_k in sorted(self._caller_all_keys.items()):
list(self._caller_all_keys.keys())) kp.set_shared_key(_hkdf_derive(base_k), idx)
elif self._caller_key: logger.info("Early-set shared_key (pre-derived) for caller indices %s",
kp.set_shared_key(_hkdf_derive(self._caller_key), 0) list(self._caller_all_keys.keys()))
logger.info("Early-set shared_key (pre-derived) caller key[0] (%d bytes)", 16) elif self._caller_key:
kp.set_shared_key(_hkdf_derive(self._caller_key), 0)
logger.info("Early-set shared_key (pre-derived) caller key[0] (%d bytes)", 16)
else:
logger.info("E2EE disabled (diagnostic mode) — skipping key setup")
# Element Call rotates its encryption key when bot joins the LiveKit room. # Element Call rotates its encryption key when bot joins the LiveKit room.
# EC sends the new key via Matrix (Megolm-encrypted); nio sync will decrypt it # EC sends the new key via Matrix (Megolm-encrypted); nio sync will decrypt it
@@ -353,7 +357,7 @@ class VoiceSession:
# Set shared_key with pre-derived AES key for caller decryption. # Set shared_key with pre-derived AES key for caller decryption.
# NOT using set_key() for caller — Rust HKDF may produce different result than EC's JS HKDF. # NOT using set_key() for caller — Rust HKDF may produce different result than EC's JS HKDF.
# set_shared_key() stores key raw (no KDF applied) — we pre-derive in Python. # set_shared_key() stores key raw (no KDF applied) — we pre-derive in Python.
if self._caller_all_keys: if kp is not None and self._caller_all_keys:
try: try:
for idx, base_k in sorted(self._caller_all_keys.items()): for idx, base_k in sorted(self._caller_all_keys.items()):
derived = _hkdf_derive(base_k) derived = _hkdf_derive(base_k)
@@ -361,7 +365,7 @@ class VoiceSession:
logger.info("Set shared_key (pre-derived)[%d] (%d bytes)", idx, len(derived)) logger.info("Set shared_key (pre-derived)[%d] (%d bytes)", idx, len(derived))
except Exception as e: except Exception as e:
logger.warning("Failed to set caller shared_key: %s", e) logger.warning("Failed to set caller shared_key: %s", e)
elif not self._caller_all_keys: elif e2ee_opts is not None and not self._caller_all_keys:
logger.warning("No caller E2EE keys — incoming audio will be silence") logger.warning("No caller E2EE keys — incoming audio will be silence")
if remote_identity: if remote_identity: