mark all inbound sessions to be backed up again when changing version

This commit is contained in:
Bruno Windels 2022-01-31 14:36:04 +01:00
parent d9e6164a5c
commit ae5cc17290
4 changed files with 37 additions and 6 deletions

View file

@ -203,21 +203,32 @@ export class Session {
this._storage.storeNames.accountData, this._storage.storeNames.accountData,
]); ]);
if (await this._createKeyBackup(key, readTxn, log)) { if (await this._createKeyBackup(key, readTxn, log)) {
await this._writeSSSSKey(key); // only after having read a secret, write the key
// as we only find out if it was good if the MAC verification succeeds
await this._writeSSSSKey(key, log);
this._keyBackup.get().flush(log); this._keyBackup.get().flush(log);
return key; return key;
} }
}); });
} }
async _writeSSSSKey(key) { async _writeSSSSKey(key, log) {
// only after having read a secret, write the key // we're going to write the 4S key, and also the backup version.
// as we only find out if it was good if the MAC verification succeeds // this way, we can detect when we enter a key for a new backup version
// and mark all inbound sessions to be backed up again
const backupVersion = this._keyBackup.get()?.version;
const writeTxn = await this._storage.readWriteTxn([ const writeTxn = await this._storage.readWriteTxn([
this._storage.storeNames.session, this._storage.storeNames.session,
this._storage.storeNames.inboundGroupSessions,
]); ]);
try { try {
ssssWriteKey(key, writeTxn); const previousBackupVersion = await ssssWriteKey(key, backupVersion, writeTxn);
log.set("previousBackupVersion", previousBackupVersion);
log.set("backupVersion", backupVersion);
if (typeof previousBackupVersion === "number" && previousBackupVersion !== backupVersion) {
const amountMarked = await this._keyBackup.markAllForBackup(writeTxn);
log.set("amountMarkedForBackup", amountMarked);
}
} catch (err) { } catch (err) {
writeTxn.abort(); writeTxn.abort();
throw err; throw err;

View file

@ -62,6 +62,10 @@ export class KeyBackup {
} }
} }
markAllForBackup(txn: Transaction): Promise<number> {
return txn.inboundGroupSessions.markAllAsNotBackedUp();
}
flush(log: ILogItem): void { flush(log: ILogItem): void {
if (!this.operationInProgress.get()) { if (!this.operationInProgress.get()) {
log.wrapDetached("flush key backup", async log => { log.wrapDetached("flush key backup", async log => {

View file

@ -27,6 +27,7 @@ import type * as OlmNamespace from "@matrix-org/olm"
type Olm = typeof OlmNamespace; type Olm = typeof OlmNamespace;
const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`; const SSSS_KEY = `${SESSION_E2EE_KEY_PREFIX}ssssKey`;
const BACKUPVERSION_KEY = `${SESSION_E2EE_KEY_PREFIX}keyBackupVersion`;
export enum KeyType { export enum KeyType {
"RecoveryKey", "RecoveryKey",
@ -49,8 +50,11 @@ async function readDefaultKeyDescription(storage: Storage): Promise<KeyDescripti
return new KeyDescription(id, keyAccountData.content as KeyDescriptionData); return new KeyDescription(id, keyAccountData.content as KeyDescriptionData);
} }
export async function writeKey(key: Key, txn: Transaction): Promise<void> { export async function writeKey(key: Key, keyBackupVersion: number, txn: Transaction): Promise<number | undefined> {
const existingVersion: number | undefined = await txn.session.get(BACKUPVERSION_KEY);
txn.session.set(BACKUPVERSION_KEY, keyBackupVersion);
txn.session.set(SSSS_KEY, {id: key.id, binaryKey: key.binaryKey}); txn.session.set(SSSS_KEY, {id: key.id, binaryKey: key.binaryKey});
return existingVersion;
} }
export async function readKey(txn: Transaction): Promise<Key | undefined> { export async function readKey(txn: Transaction): Promise<Key | undefined> {

View file

@ -91,4 +91,16 @@ export class InboundGroupSessionStore {
this._store.put(entry); this._store.put(entry);
} }
} }
async markAllAsNotBackedUp(): Promise<number> {
const backedUpKey = this._store.IDBKeyRange.only(BackupStatus.BackedUp);
let count = 0;
await this._store.index("byBackup").iterateValues(backedUpKey, (val: InboundGroupSessionEntry, key: IDBValidKey, cur: IDBCursorWithValue) => {
val.backup = BackupStatus.NotBackedUp;
cur.update(val);
count += 1;
return false;
});
return count;
}
} }