From fa5b014abec5f71f8c2f8ef3ea46742011547cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Tue, 22 Aug 2023 17:23:29 +0200 Subject: [PATCH] E2EE for embeded mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/e2ee/matrixKeyProvider.ts | 81 +++++++++++++++++++++++++++++++++++ src/livekit/useLiveKit.ts | 5 ++- src/room/InCallView.tsx | 1 + 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/e2ee/matrixKeyProvider.ts diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts new file mode 100644 index 00000000..2d0bc1a8 --- /dev/null +++ b/src/e2ee/matrixKeyProvider.ts @@ -0,0 +1,81 @@ +/* +Copyright 2023 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { logger } from "@sentry/utils"; +import { + BaseKeyProvider, + KeyProviderOptions, + createKeyMaterialFromString, +} from "livekit-client"; +import { CallMembership } from "matrix-js-sdk/src/matrixrtc/CallMembership"; +import { + MatrixRTCSession, + MatrixRTCSessionEvent, +} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; + +export class MatrixKeyProvider extends BaseKeyProvider { + constructor( + private rtcSession: MatrixRTCSession, + keyProviderOptions: Partial = {} + ) { + super(keyProviderOptions); + + const encryptionKey = this.rtcSession.activeEncryptionKey; + if (!encryptionKey) { + throw new Error( + "MatrixKeyProvider requires the given MatrixRTCSession to have an activeEncryptionKey" + ); + } + + this.rtcSession.on( + MatrixRTCSessionEvent.MembershipsChanged, + this.onMemberShipsChanged + ); + this.rtcSession.on( + MatrixRTCSessionEvent.ActiveEncryptionKeyChanged, + this.onEncryptionKeyChanged + ); + + this.onEncryptionKeyChanged(encryptionKey); + this.onMemberShipsChanged([], this.rtcSession.memberships); + } + + private onEncryptionKeyChanged = async (key: string) => { + this.onSetEncryptionKey(await createKeyMaterialFromString(key), undefined); + }; + + private onMemberShipsChanged = async ( + _: CallMembership[], + newMemberships: CallMembership[] + ) => { + for (const membership of newMemberships) { + const participantId = `${membership.member.userId}:${membership.deviceId}`; + const encryptionKey = await membership.getActiveEncryptionKey(); + + if (!encryptionKey) { + logger.warn( + `Participant ${participantId} did not share a key over Matrix` + ); + continue; + } + + this.onSetEncryptionKey( + await createKeyMaterialFromString(encryptionKey), + participantId + ); + } + }; +} diff --git a/src/livekit/useLiveKit.ts b/src/livekit/useLiveKit.ts index 1f5704b3..5adccee1 100644 --- a/src/livekit/useLiveKit.ts +++ b/src/livekit/useLiveKit.ts @@ -17,7 +17,6 @@ limitations under the License. import { ConnectionState, E2EEOptions, - ExternalE2EEKeyProvider, Room, RoomOptions, setLogLevel, @@ -26,6 +25,8 @@ import { useLiveKitRoom } from "@livekit/components-react"; import { useEffect, useMemo, useRef } from "react"; import E2EEWorker from "livekit-client/e2ee-worker?worker"; import { logger } from "matrix-js-sdk/src/logger"; +import { MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; +import { ExternalE2EEKeyProvider } from "livekit-client/dist/src/e2ee/KeyProvider"; import { defaultLiveKitOptions } from "./options"; import { SFUConfig } from "./openIDSFU"; @@ -39,6 +40,7 @@ import { ECConnectionState, useECConnectionState, } from "./useECConnectionState"; +import { MatrixKeyProvider } from "../e2ee/matrixKeyProvider"; export type E2EEConfig = { sharedKey: string; @@ -53,6 +55,7 @@ interface UseLivekitResult { export function useLiveKit( muteStates: MuteStates, + rtcSession: MatrixRTCSession, sfuConfig?: SFUConfig, e2eeConfig?: E2EEConfig ): UseLivekitResult { diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 76cb7c07..22723a08 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -95,6 +95,7 @@ export function ActiveCall(props: ActiveCallProps) { const sfuConfig = useOpenIDSFU(props.client, props.rtcSession); const { livekitRoom, connState } = useLiveKit( props.muteStates, + props.rtcSession, sfuConfig, props.e2eeConfig );