Skip to content

Commit 909caab

Browse files
andybalaamrichvdh
andauthored
Don't run migration for Rust crypto if the legacy store is empty (#4218)
* Don't run migration for Rust crypto if the legacy store is empty Fixes element-hq/element-web#27447 * Add copyright for the TypeScript files in legacy DB dumps * Provide a type for the accountPickle we check for before migration * Remove redundant backup response This is unused * Simplify keys response * Downgrade log message. --------- Co-authored-by: Richard van der Hoff <[email protected]>
1 parent 7c87625 commit 909caab

File tree

8 files changed

+153
-0
lines changed

8 files changed

+153
-0
lines changed

spec/integ/crypto/rust-crypto.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { populateStore } from "../../test-utils/test_indexeddb_cryptostore_dump"
2323
import { MSK_NOT_CACHED_DATASET } from "../../test-utils/test_indexeddb_cryptostore_dump/no_cached_msk_dump";
2424
import { IDENTITY_NOT_TRUSTED_DATASET } from "../../test-utils/test_indexeddb_cryptostore_dump/unverified";
2525
import { FULL_ACCOUNT_DATASET } from "../../test-utils/test_indexeddb_cryptostore_dump/full_account";
26+
import { EMPTY_ACCOUNT_DATASET } from "../../test-utils/test_indexeddb_cryptostore_dump/empty_account";
2627

2728
jest.setTimeout(15000);
2829

@@ -304,6 +305,38 @@ describe("MatrixClient.initRustCrypto", () => {
304305
});
305306
});
306307

308+
it("should not migrate if account data is missing", async () => {
309+
// See https://github.com/element-hq/element-web/issues/27447
310+
311+
// Given we have an almost-empty legacy account in the database
312+
fetchMock.get("path:/_matrix/client/v3/room_keys/version", {
313+
status: 404,
314+
body: { errcode: "M_NOT_FOUND", error: "No backup found" },
315+
});
316+
fetchMock.post("path:/_matrix/client/v3/keys/query", EMPTY_ACCOUNT_DATASET.keyQueryResponse);
317+
318+
const testStoreName = "test-store";
319+
await populateStore(testStoreName, EMPTY_ACCOUNT_DATASET.dumpPath);
320+
const cryptoStore = new IndexedDBCryptoStore(indexedDB, testStoreName);
321+
322+
const matrixClient = createClient({
323+
baseUrl: "http://test.server",
324+
userId: EMPTY_ACCOUNT_DATASET.userId,
325+
deviceId: EMPTY_ACCOUNT_DATASET.deviceId,
326+
cryptoStore,
327+
pickleKey: EMPTY_ACCOUNT_DATASET.pickleKey,
328+
});
329+
330+
// When we start Rust crypto, potentially triggering an upgrade
331+
const progressListener = jest.fn();
332+
matrixClient.addListener(CryptoEvent.LegacyCryptoStoreMigrationProgress, progressListener);
333+
334+
await matrixClient.initRustCrypto();
335+
336+
// Then no error occurs, and no upgrade happens
337+
expect(progressListener.mock.calls.length).toBe(0);
338+
}, 60000);
339+
307340
describe("Legacy trust migration", () => {
308341
async function populateAndStartLegacyCryptoStore(dumpPath: string): Promise<IndexedDBCryptoStore> {
309342
const testStoreName = "test-store";
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Dump of an empty libolm indexeddb cryptostore to test skipping migration
2+
3+
A dump of an account which is almost completely empty, and totally unsuitable
4+
for use as a real account.
5+
6+
This dump was manually created by copying and editing full_account.
7+
8+
Created to test
9+
["Unable to restore session" error due due to half-initialised legacy indexeddb crypto store #27447](https://github.com/element-hq/element-web/issues/27447).
10+
We should not launch the Rust migration code when we find a DB in this state.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"account": [],
3+
"device_data": [],
4+
"inbound_group_sessions": [],
5+
"inbound_group_sessions_withheld": [],
6+
"notified_error_devices": [],
7+
"outgoingRoomKeyRequests": [],
8+
"parked_shared_history": [],
9+
"rooms": [],
10+
"session_problems": [],
11+
"sessions": [],
12+
"sessions_needing_backup": [],
13+
"shared_history_inbound_group_sessions": []
14+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright 2024 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { DumpDataSetInfo } from "../index";
18+
19+
/**
20+
* A key query response containing the current keys of the tested user.
21+
* To be used during tests with fetchmock.
22+
*/
23+
const KEYS_QUERY_RESPONSE = { device_keys: { "@emptyuser:example.com": {} } };
24+
25+
/**
26+
* A dataset containing the information for the tested user.
27+
* To be used during tests.
28+
*/
29+
export const EMPTY_ACCOUNT_DATASET: DumpDataSetInfo = {
30+
userId: "@emptyuser:example.com",
31+
deviceId: "EMPTYDEVIC",
32+
pickleKey: "+/bcdefghijklmnopqrstu1/zyxvutsrqponmlkjih2",
33+
keyQueryResponse: KEYS_QUERY_RESPONSE,
34+
dumpPath: "spec/test-utils/test_indexeddb_cryptostore_dump/empty_account/dump.json",
35+
};

spec/test-utils/test_indexeddb_cryptostore_dump/full_account/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2024 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
import { DumpDataSetInfo } from "../index";
218

319
/**

spec/test-utils/test_indexeddb_cryptostore_dump/no_cached_msk_dump/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2024 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
import { KeyBackupInfo } from "../../../../src/crypto-api/keybackup";
218
import { DumpDataSetInfo } from "../index";
319

spec/test-utils/test_indexeddb_cryptostore_dump/unverified/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
Copyright 2024 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
117
import { DumpDataSetInfo } from "../index";
218

319
/**

src/rust-crypto/libolm_migration.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,19 @@ export async function migrateFromLegacyCrypto(args: {
8383
}
8484

8585
await legacyStore.startup();
86+
87+
let accountPickle: string | null = null;
88+
await legacyStore.doTxn("readonly", [IndexedDBCryptoStore.STORE_ACCOUNT], (txn) => {
89+
legacyStore.getAccount(txn, (acctPickle) => {
90+
accountPickle = acctPickle;
91+
});
92+
});
93+
if (!accountPickle) {
94+
// This store is not properly set up. Nothing to migrate.
95+
logger.debug("Legacy crypto store is not set up (no account found). Not migrating.");
96+
return;
97+
}
98+
8699
let migrationState = await legacyStore.getMigrationState();
87100

88101
if (migrationState >= MigrationState.MEGOLM_SESSIONS_MIGRATED) {

0 commit comments

Comments
 (0)