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
This commit is contained in:
Bruno Windels 2022-01-28 13:07:49 +01:00
parent c81dde53e7
commit a499689bd8
3 changed files with 40 additions and 25 deletions

View file

@ -15,12 +15,14 @@ limitations under the License.
*/ */
import {MEGOLM_ALGORITHM} from "../common.js"; import {MEGOLM_ALGORITHM} from "../common.js";
import {OutboundRoomKey} from "./decryption/RoomKey";
export class Encryption { export class Encryption {
constructor({pickleKey, olm, account, storage, now, ownDeviceId}) { constructor({pickleKey, olm, account, keyLoader, storage, now, ownDeviceId}) {
this._pickleKey = pickleKey; this._pickleKey = pickleKey;
this._olm = olm; this._olm = olm;
this._account = account; this._account = account;
this._keyLoader = keyLoader;
this._storage = storage; this._storage = storage;
this._now = now; this._now = now;
this._ownDeviceId = ownDeviceId; this._ownDeviceId = ownDeviceId;
@ -64,7 +66,7 @@ export class Encryption {
let roomKeyMessage; let roomKeyMessage;
try { try {
let sessionEntry = await txn.outboundGroupSessions.get(roomId); 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) { if (roomKeyMessage) {
this._writeSession(this._now(), session, roomId, txn); 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) { if (sessionEntry) {
session.unpickle(this._pickleKey, sessionEntry.session); session.unpickle(this._pickleKey, sessionEntry.session);
} }
@ -91,7 +93,8 @@ export class Encryption {
} }
session.create(); session.create();
const roomKeyMessage = this._createRoomKeyMessage(session, roomId); 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; return roomKeyMessage;
} }
} }
@ -123,7 +126,7 @@ export class Encryption {
let encryptedContent; let encryptedContent;
try { try {
let sessionEntry = await txn.outboundGroupSessions.get(roomId); 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); encryptedContent = this._encryptContent(roomId, session, type, content);
// update timestamp when a new session is created // update timestamp when a new session is created
const createdAt = roomKeyMessage ? this._now() : sessionEntry.createdAt; const createdAt = roomKeyMessage ? this._now() : sessionEntry.createdAt;
@ -190,26 +193,6 @@ export class Encryption {
chain_index: session.message_index() 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();
}
}
} }
/** /**

View file

@ -155,7 +155,38 @@ class DeviceMessageRoomKey extends IncomingRoomKey {
loadInto(session) { loadInto(session) {
session.create(this.serializationKey); 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 { class BackupRoomKey extends IncomingRoomKey {

View file

@ -25,6 +25,7 @@ export enum BackupStatus {
export enum KeySource { export enum KeySource {
DeviceMessage = 1, DeviceMessage = 1,
Backup, Backup,
Outbound
} }
export interface InboundGroupSessionEntry { export interface InboundGroupSessionEntry {