From a499689bd857ea5cf391eba074b9d4dc8704c512 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Fri, 28 Jan 2022 13:07:49 +0100 Subject: [PATCH] also write room key that we create ourselves with RoomKey infrastructure so all keys are written in one place and the flags are always correct --- src/matrix/e2ee/megolm/Encryption.js | 33 +++++-------------- src/matrix/e2ee/megolm/decryption/RoomKey.ts | 31 +++++++++++++++++ .../idb/stores/InboundGroupSessionStore.ts | 1 + 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/matrix/e2ee/megolm/Encryption.js b/src/matrix/e2ee/megolm/Encryption.js index bd2311d7..eb5f68d3 100644 --- a/src/matrix/e2ee/megolm/Encryption.js +++ b/src/matrix/e2ee/megolm/Encryption.js @@ -15,12 +15,14 @@ limitations under the License. */ import {MEGOLM_ALGORITHM} from "../common.js"; +import {OutboundRoomKey} from "./decryption/RoomKey"; export class Encryption { - constructor({pickleKey, olm, account, storage, now, ownDeviceId}) { + constructor({pickleKey, olm, account, keyLoader, storage, now, ownDeviceId}) { this._pickleKey = pickleKey; this._olm = olm; this._account = account; + this._keyLoader = keyLoader; this._storage = storage; this._now = now; this._ownDeviceId = ownDeviceId; @@ -64,7 +66,7 @@ export class Encryption { let roomKeyMessage; try { let sessionEntry = await txn.outboundGroupSessions.get(roomId); - roomKeyMessage = this._readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn); + roomKeyMessage = await this._readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn); if (roomKeyMessage) { this._writeSession(this._now(), session, roomId, txn); } @@ -79,7 +81,7 @@ export class Encryption { } } - _readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn) { + async _readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn) { if (sessionEntry) { session.unpickle(this._pickleKey, sessionEntry.session); } @@ -91,7 +93,8 @@ export class Encryption { } session.create(); const roomKeyMessage = this._createRoomKeyMessage(session, roomId); - this._storeAsInboundSession(session, roomId, txn); + const roomKey = new OutboundRoomKey(roomId, session, this._account.identityKeys); + await roomKey.write(this._keyLoader, txn); return roomKeyMessage; } } @@ -123,7 +126,7 @@ export class Encryption { let encryptedContent; try { let sessionEntry = await txn.outboundGroupSessions.get(roomId); - roomKeyMessage = this._readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn); + roomKeyMessage = await this._readOrCreateSession(session, sessionEntry, roomId, encryptionParams, txn); encryptedContent = this._encryptContent(roomId, session, type, content); // update timestamp when a new session is created const createdAt = roomKeyMessage ? this._now() : sessionEntry.createdAt; @@ -190,26 +193,6 @@ export class Encryption { chain_index: session.message_index() } } - - _storeAsInboundSession(outboundSession, roomId, txn) { - const {identityKeys} = this._account; - const claimedKeys = {ed25519: identityKeys.ed25519}; - const session = new this._olm.InboundGroupSession(); - try { - session.create(outboundSession.session_key()); - const sessionEntry = { - roomId, - senderKey: identityKeys.curve25519, - sessionId: session.session_id(), - session: session.pickle(this._pickleKey), - claimedKeys, - }; - txn.inboundGroupSessions.set(sessionEntry); - return sessionEntry; - } finally { - session.free(); - } - } } /** diff --git a/src/matrix/e2ee/megolm/decryption/RoomKey.ts b/src/matrix/e2ee/megolm/decryption/RoomKey.ts index 7b648d92..f4812acc 100644 --- a/src/matrix/e2ee/megolm/decryption/RoomKey.ts +++ b/src/matrix/e2ee/megolm/decryption/RoomKey.ts @@ -155,7 +155,38 @@ class DeviceMessageRoomKey extends IncomingRoomKey { loadInto(session) { session.create(this.serializationKey); } +} +// a room key we send out ourselves, +// here adapted to write it as an incoming key +// as we don't send it to ourself with a to_device msg +export class OutboundRoomKey extends IncomingRoomKey { + private _sessionKey: string; + + constructor( + private readonly _roomId: string, + private readonly outboundSession: Olm.OutboundGroupSession, + private readonly identityKeys: {[algo: string]: string} + ) { + super(); + // this is a new key, so always better than what might be in storage, no need to check + this.isBetter = true; + // cache this, as it is used by key loader to find a matching key and + // this calls into WASM so is not just reading a prop + this._sessionKey = this.outboundSession.session_key(); + } + + get roomId(): string { return this._roomId; } + get senderKey(): string { return this.identityKeys.curve25519; } + get sessionId(): string { return this.outboundSession.session_id(); } + get claimedEd25519Key(): string { return this.identityKeys.ed25519; } + get serializationKey(): string { return this._sessionKey; } + get serializationType(): string { return "create"; } + protected get keySource(): KeySource { return KeySource.Outbound; } + + loadInto(session: Olm.InboundGroupSession) { + session.create(this.serializationKey); + } } class BackupRoomKey extends IncomingRoomKey { diff --git a/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts b/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts index 96b127f7..f16872a7 100644 --- a/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts +++ b/src/matrix/storage/idb/stores/InboundGroupSessionStore.ts @@ -25,6 +25,7 @@ export enum BackupStatus { export enum KeySource { DeviceMessage = 1, Backup, + Outbound } export interface InboundGroupSessionEntry {