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 frame cryptor is first created it enters DEC_FAILED and drops all frames
# even after the key is set later.
kp = self.lk_room.e2ee_manager.key_provider
kp.set_key(bot_identity, self._bot_key, 0)
logger.info("Set bot raw key for %s (%d bytes)", bot_identity, len(self._bot_key))
# Caller keys: use set_shared_key with pre-derived AES (bypasses Rust HKDF).
# Per-participant set_key is NOT called for caller — Rust HKDF may not match EC's JS HKDF.
if self._caller_all_keys:
for idx, base_k in sorted(self._caller_all_keys.items()):
kp.set_shared_key(_hkdf_derive(base_k), idx)
logger.info("Early-set shared_key (pre-derived) for caller indices %s",
list(self._caller_all_keys.keys()))
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)
kp = None
if e2ee_opts is not None:
kp = self.lk_room.e2ee_manager.key_provider
kp.set_key(bot_identity, self._bot_key, 0)
logger.info("Set bot raw key for %s (%d bytes)", bot_identity, len(self._bot_key))
# Caller keys: use set_shared_key with pre-derived AES (bypasses Rust HKDF).
# Per-participant set_key is NOT called for caller — Rust HKDF may not match EC's JS HKDF.
if self._caller_all_keys:
for idx, base_k in sorted(self._caller_all_keys.items()):
kp.set_shared_key(_hkdf_derive(base_k), idx)
logger.info("Early-set shared_key (pre-derived) for caller indices %s",
list(self._caller_all_keys.keys()))
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.
# 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.
# 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.
if self._caller_all_keys:
if kp is not None and self._caller_all_keys:
try:
for idx, base_k in sorted(self._caller_all_keys.items()):
derived = _hkdf_derive(base_k)
@@ -361,7 +365,7 @@ class VoiceSession:
logger.info("Set shared_key (pre-derived)[%d] (%d bytes)", idx, len(derived))
except Exception as 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")
if remote_identity: