diff --git a/spec/integ/crypto/rust-crypto.spec.ts b/spec/integ/crypto/rust-crypto.spec.ts index 5d5a84819..762bfa0cf 100644 --- a/spec/integ/crypto/rust-crypto.spec.ts +++ b/spec/integ/crypto/rust-crypto.spec.ts @@ -112,6 +112,78 @@ describe("MatrixClient.initRustCrypto", () => { count: 79, }); + fetchMock.post("path:/_matrix/client/v3/keys/query", { + device_keys: { + "@vdhtest200713:matrix.org": { + KMFSTJSMLB: { + algorithms: ["m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"], + device_id: "KMFSTJSMLB", + keys: { + "curve25519:KMFSTJSMLB": "LKv0bKbc0EC4h0jknbemv3QalEkeYvuNeUXVRgVVTTU", + "ed25519:KMFSTJSMLB": "qK70DEqIXq7T+UU3v/al47Ab4JkMEBLpNrTBMbS5rrw", + }, + user_id: "@vdhtest200713:matrix.org", + signatures: { + "@vdhtest200713:matrix.org": { + "ed25519:KMFSTJSMLB": + "aE+PdxLAdwQ/xfJwLmqebvt/lrT97fZas2SQFFrM+dPmHxQtjyS8csm88BLfGRjJKK1B/vWev3AaKqQZwLTUAw", + "ed25519:lDvg6vi3P80L9XFNpUSU+5Y87m3p6yHcC83jhSU4Q5k": + "lCd4SA/JT1nnxsgN9yQaLJQhH5hkLMVVx6ba5JAjL1wpWVqyPxzMJHImX6vTztk6S8rybcdfYkea5W/Ii+4HCQ", + }, + }, + }, + }, + }, + master_keys: { + "@vdhtest200713:matrix.org": { + user_id: "@vdhtest200713:matrix.org", + usage: ["master"], + keys: { + "ed25519:gh9fGr39eNZUdWynEMJ/q/WZq/Pk/foFxHXFBFm18ZI": + "gh9fGr39eNZUdWynEMJ/q/WZq/Pk/foFxHXFBFm18ZI", + }, + signatures: { + "@vdhtest200713:matrix.org": { + "ed25519:MWOGVUTXZN": + "stOu1aHbhsWB/Aj5M/HqBR83QzME+682C995Uc8JxSmmyrlWmgG8QrnoUDG2OFR1t6zNQ+QLEilU4WNEOV73DQ", + }, + }, + }, + }, + self_signing_keys: { + "@vdhtest200713:matrix.org": { + user_id: "@vdhtest200713:matrix.org", + usage: ["self_signing"], + keys: { + "ed25519:lDvg6vi3P80L9XFNpUSU+5Y87m3p6yHcC83jhSU4Q5k": + "lDvg6vi3P80L9XFNpUSU+5Y87m3p6yHcC83jhSU4Q5k", + }, + signatures: { + "@vdhtest200713:matrix.org": { + "ed25519:gh9fGr39eNZUdWynEMJ/q/WZq/Pk/foFxHXFBFm18ZI": + "HKTC7NoBhAkfJtmemmkn/HvCCgBQViWZ0uH7aGPRaWMDFgD8T7Q+y1j3FKZv4mhSopR85Fq3FRyXsG8OVvGeBA", + }, + }, + }, + }, + user_signing_keys: { + "@vdhtest200713:matrix.org": { + user_id: "@vdhtest200713:matrix.org", + usage: ["user_signing"], + keys: { + "ed25519:YShqO/3u5vQ0uucojraWrtoLrek0CYrurN/vH/YPMg8": + "YShqO/3u5vQ0uucojraWrtoLrek0CYrurN/vH/YPMg8", + }, + signatures: { + "@vdhtest200713:matrix.org": { + "ed25519:gh9fGr39eNZUdWynEMJ/q/WZq/Pk/foFxHXFBFm18ZI": + "u8VOi4IaeRJwDgy2ftK02NJQPdBijy8f/0+WnHGG72yfOvMthwWzEw8SrRSNG8glBNrfHinKwCyJJzAJwyepCQ", + }, + }, + }, + }, + }); + const testStoreName = "test-store"; await populateStore(testStoreName); const cryptoStore = new IndexedDBCryptoStore(indexedDB, testStoreName); @@ -129,6 +201,15 @@ describe("MatrixClient.initRustCrypto", () => { await matrixClient.initRustCrypto(); + const verificationStatus = await matrixClient + .getCrypto()! + .getDeviceVerificationStatus("@vdhtest200713:matrix.org", "KMFSTJSMLB"); + + // Check that the current device and identity trust is migrated correctly just after migration + expect(verificationStatus).toBeDefined(); + expect(verificationStatus!.crossSigningVerified).toEqual(true); + expect(verificationStatus!.signedByOwner).toEqual(true); + // Do some basic checks on the imported data const deviceKeys = await matrixClient.getCrypto()!.getOwnDeviceKeys(); expect(deviceKeys.curve25519).toEqual("LKv0bKbc0EC4h0jknbemv3QalEkeYvuNeUXVRgVVTTU"); diff --git a/src/crypto/store/base.ts b/src/crypto/store/base.ts index d523981b2..e978b24e3 100644 --- a/src/crypto/store/base.ts +++ b/src/crypto/store/base.ts @@ -335,6 +335,10 @@ export enum MigrationState { /** MEGOLM_SESSIONS_MIGRATED, and in addition, we have migrated all the room settings. */ ROOM_SETTINGS_MIGRATED, + + /** ROOM_SETTINGS_MIGRATED, and in addition, we have done the first own keys query in order to + * load the public part of the keys that have been migrated */ + INITIAL_OWN_KEY_QUERY_DONE, } /** diff --git a/src/rust-crypto/index.ts b/src/rust-crypto/index.ts index abbab62ad..e3c34a6db 100644 --- a/src/rust-crypto/index.ts +++ b/src/rust-crypto/index.ts @@ -22,7 +22,7 @@ import { IHttpOpts, MatrixHttpApi } from "../http-api"; import { ServerSideSecretStorage } from "../secret-storage"; import { ICryptoCallbacks } from "../crypto"; import { Logger } from "../logger"; -import { CryptoStore } from "../crypto/store/base"; +import { CryptoStore, MigrationState } from "../crypto/store/base"; import { migrateFromLegacyCrypto, migrateRoomSettingsFromLegacyCrypto } from "./libolm_migration"; /** @@ -152,6 +152,7 @@ async function initOlmMachine( olmMachine.roomKeyRequestsEnabled = false; const rustCrypto = new RustCrypto(logger, olmMachine, http, userId, deviceId, secretStorage, cryptoCallbacks); + await olmMachine.registerRoomKeyUpdatedCallback((sessions: RustSdkCryptoJs.RoomKeyInfo[]) => rustCrypto.onRoomKeysUpdated(sessions), ); @@ -182,5 +183,23 @@ async function initOlmMachine( // XXX: find a less hacky way to do this. await olmMachine.outgoingRequests(); + if (legacyCryptoStore && (await legacyCryptoStore.containsData())) { + const migrationState = await legacyCryptoStore.getMigrationState(); + if (migrationState < MigrationState.INITIAL_OWN_KEY_QUERY_DONE) { + logger.debug(`Performing initial key query after migration`); + // We need to do an initial keys query so that the rust stack can properly update trust of + // the user device and identity from the migrated private keys. + // If not done, there is a short period where the own device/identity trust will be undefined after migration. + try { + await rustCrypto.userHasCrossSigningKeys(userId); + } catch (e) { + // We don't want to fail the startup if this fails, but we do want to log it. + // It will be retried by the sdk. + logger.error("Failed to check for cross-signing keys after migration", e); + } + await legacyCryptoStore.setMigrationState(MigrationState.INITIAL_OWN_KEY_QUERY_DONE); + } + } + return rustCrypto; }