mark all inbound sessions to be backed up again when changing version
This commit is contained in:
parent
d9e6164a5c
commit
ae5cc17290
4 changed files with 37 additions and 6 deletions
|
@ -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;
|
||||||
|
|
|
@ -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 => {
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue