You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-07 23:02:56 +03:00
MatrixRTC: comply with the manageMediaKeys
EncryptionConfig option (#4942)
* MatrixRTC: comply with the `manageMediaKeys` JoinConfig option * add additional test for reception * add comments about temporary solution
This commit is contained in:
@@ -448,6 +448,23 @@ describe("RTCEncryptionManager", () => {
|
|||||||
|
|
||||||
expect(statistics.counters.roomEventEncryptionKeysSent).toBe(2);
|
expect(statistics.counters.roomEventEncryptionKeysSent).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should not distribute keys if encryption is disabled", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
const members = [
|
||||||
|
aCallMembership("@bob:example.org", "BOBDEVICE"),
|
||||||
|
aCallMembership("@bob:example.org", "BOBDEVICE2"),
|
||||||
|
aCallMembership("@carl:example.org", "CARLDEVICE"),
|
||||||
|
];
|
||||||
|
getMembershipMock.mockReturnValue(members);
|
||||||
|
|
||||||
|
encryptionManager.join({ manageMediaKeys: false });
|
||||||
|
encryptionManager.onMembershipsUpdate();
|
||||||
|
await jest.runOnlyPendingTimersAsync();
|
||||||
|
|
||||||
|
expect(mockTransport.sendKey).not.toHaveBeenCalled();
|
||||||
|
expect(onEncryptionKeysChanged).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Receiving Keys", () => {
|
describe("Receiving Keys", () => {
|
||||||
@@ -471,6 +488,29 @@ describe("RTCEncryptionManager", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not accept keys when manageMediaKeys is disabled", async () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const members = [aCallMembership("@bob:example.org", "BOBDEVICE")];
|
||||||
|
getMembershipMock.mockReturnValue(members);
|
||||||
|
|
||||||
|
encryptionManager.join({ manageMediaKeys: false });
|
||||||
|
encryptionManager.onMembershipsUpdate();
|
||||||
|
await jest.advanceTimersByTimeAsync(10);
|
||||||
|
|
||||||
|
mockTransport.emit(
|
||||||
|
KeyTransportEvents.ReceivedKeys,
|
||||||
|
"@bob:example.org",
|
||||||
|
"BOBDEVICE",
|
||||||
|
"AAAAAAAAAAA",
|
||||||
|
0 /* KeyId */,
|
||||||
|
0 /* Timestamp */,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(onEncryptionKeysChanged).not.toHaveBeenCalled();
|
||||||
|
expect(statistics.counters.roomEventEncryptionKeysReceived).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("should accept keys from transport", async () => {
|
it("should accept keys from transport", async () => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
@@ -46,6 +46,11 @@ import {
|
|||||||
* XXX In the future we want to distribute a ratcheted key not the current one for new joiners.
|
* XXX In the future we want to distribute a ratcheted key not the current one for new joiners.
|
||||||
*/
|
*/
|
||||||
export class RTCEncryptionManager implements IEncryptionManager {
|
export class RTCEncryptionManager implements IEncryptionManager {
|
||||||
|
// This is a stop-gap solution for now. The preferred way to handle this case would be instead
|
||||||
|
// to create a NoOpEncryptionManager that does nothing and use it for the session.
|
||||||
|
// This will be done when removing the legacy EncryptionManager.
|
||||||
|
private manageMediaKeys = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the key rings for each participant.
|
* Store the key rings for each participant.
|
||||||
* The encryption manager stores the keys because the application layer might not be ready yet to handle the keys.
|
* The encryption manager stores the keys because the application layer might not be ready yet to handle the keys.
|
||||||
@@ -126,6 +131,8 @@ export class RTCEncryptionManager implements IEncryptionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public join(joinConfig: EncryptionConfig | undefined): void {
|
public join(joinConfig: EncryptionConfig | undefined): void {
|
||||||
|
this.manageMediaKeys = joinConfig?.manageMediaKeys ?? true; // default to true
|
||||||
|
|
||||||
this.logger?.info(`Joining room`);
|
this.logger?.info(`Joining room`);
|
||||||
this.useKeyDelay = joinConfig?.useKeyDelay ?? 1000;
|
this.useKeyDelay = joinConfig?.useKeyDelay ?? 1000;
|
||||||
this.keyRotationGracePeriodMs = joinConfig?.keyRotationGracePeriodMs ?? 10_000;
|
this.keyRotationGracePeriodMs = joinConfig?.keyRotationGracePeriodMs ?? 10_000;
|
||||||
@@ -174,6 +181,10 @@ export class RTCEncryptionManager implements IEncryptionManager {
|
|||||||
* the calls will be coalesced to a single new distribution (that will start just after the current one has completed).
|
* the calls will be coalesced to a single new distribution (that will start just after the current one has completed).
|
||||||
*/
|
*/
|
||||||
private ensureKeyDistribution(): void {
|
private ensureKeyDistribution(): void {
|
||||||
|
// `manageMediaKeys` is a stop-gap solution for now. The preferred way to handle this case would be instead
|
||||||
|
// to create a NoOpEncryptionManager that does nothing and use it for the session.
|
||||||
|
// This will be done when removing the legacy EncryptionManager.
|
||||||
|
if (!this.manageMediaKeys) return;
|
||||||
if (this.currentKeyDistributionPromise == null) {
|
if (this.currentKeyDistributionPromise == null) {
|
||||||
this.logger?.debug(`No active rollout, start a new one`);
|
this.logger?.debug(`No active rollout, start a new one`);
|
||||||
// start a rollout
|
// start a rollout
|
||||||
@@ -196,6 +207,15 @@ export class RTCEncryptionManager implements IEncryptionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onNewKeyReceived: KeyTransportEventListener = (userId, deviceId, keyBase64Encoded, index, timestamp) => {
|
public onNewKeyReceived: KeyTransportEventListener = (userId, deviceId, keyBase64Encoded, index, timestamp) => {
|
||||||
|
// `manageMediaKeys` is a stop-gap solution for now. The preferred way to handle this case would be instead
|
||||||
|
// to create a NoOpEncryptionManager that does nothing and use it for the session.
|
||||||
|
// This will be done when removing the legacy EncryptionManager.
|
||||||
|
if (!this.manageMediaKeys) {
|
||||||
|
this.logger?.warn(
|
||||||
|
`Received key over transport ${userId}:${deviceId} at index ${index} but media keys are disabled`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.logger?.debug(`Received key over transport ${userId}:${deviceId} at index ${index}`);
|
this.logger?.debug(`Received key over transport ${userId}:${deviceId} at index ${index}`);
|
||||||
|
|
||||||
// We received a new key, notify the video layer of this new key so that it can decrypt the frames properly.
|
// We received a new key, notify the video layer of this new key so that it can decrypt the frames properly.
|
||||||
|
Reference in New Issue
Block a user