Skip to content

Commit

Permalink
don't back up keys that we got from backup
Browse files Browse the repository at this point in the history
  • Loading branch information
uhoreg committed Nov 30, 2023
1 parent 67019a3 commit 0a24d42
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 8 deletions.
46 changes: 46 additions & 0 deletions spec/unit/rust-crypto/rust-crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
EventShieldReason,
ImportRoomKeysOpts,
KeyBackupCheck,
RoomKeySource,
VerificationRequest,
} from "../../../src/crypto-api";
import * as testData from "../../test-utils/test-data";
Expand Down Expand Up @@ -931,6 +932,51 @@ describe("RustCrypto", () => {
await rustCrypto.onUserIdentityUpdated(new RustSdkCryptoJs.UserId(testData.TEST_USER_ID));
expect(await keyBackupStatusPromise).toBe(true);
});

it("does not back up keys that came from backup", async () => {
const rustCrypto = await makeTestRustCrypto();

const olmMachine = rustCrypto.getOlmMachineOrThrow();

await olmMachine.enableBackupV1(
testData.SIGNED_BACKUP_DATA.auth_data.public_key,
testData.SIGNED_BACKUP_DATA.version,
);

// we import two keys: one "from backup", and one "from export"
const [backedUpRoomKey, exportedRoomKey, ..._] = testData.MEGOLM_SESSION_DATA_ARRAY;
await rustCrypto.importRoomKeys([backedUpRoomKey], {
source: RoomKeySource.Backup,
});
await rustCrypto.importRoomKeys([exportedRoomKey]);

// we ask for the keys that should be backed up
const roomKeysRequest = await olmMachine.backupRoomKeys();
expect(roomKeysRequest).toBeTruthy();
const roomKeys = JSON.parse(roomKeysRequest!.body);

// we expect that the key "from export" is present
expect(roomKeys).toMatchObject({
"rooms": {
[exportedRoomKey.room_id]: {
sessions: {
[exportedRoomKey.session_id]: {}
}
}
}
});

// we expect that the key "from backup" is not present
expect(roomKeys).not.toMatchObject({
"rooms": {
[backedUpRoomKey.room_id]: {
sessions: {
[backedUpRoomKey.session_id]: {}
}
}
}
});
});
});
});

Expand Down
4 changes: 2 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ import { LocalNotificationSettings } from "./@types/local_notifications";
import { buildFeatureSupportMap, Feature, ServerSupport } from "./feature";
import { CryptoBackend } from "./common-crypto/CryptoBackend";
import { RUST_SDK_STORE_PREFIX } from "./rust-crypto/constants";
import { BootstrapCrossSigningOpts, CrossSigningKeyInfo, CryptoApi, ImportRoomKeysOpts } from "./crypto-api";
import { BootstrapCrossSigningOpts, CrossSigningKeyInfo, CryptoApi, ImportRoomKeysOpts, RoomKeySource } from "./crypto-api";
import { DeviceInfoMap } from "./crypto/DeviceList";
import {
AddSecretStorageKeyOpts,
Expand Down Expand Up @@ -3974,7 +3974,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
await this.cryptoBackend.importRoomKeys(keys, {
progressCallback,
untrusted,
source: "backup",
source: RoomKeySource.Backup,
});

/// in case entering the passphrase would add a new signature?
Expand Down
17 changes: 16 additions & 1 deletion src/crypto-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,20 @@ export interface ImportRoomKeyProgressData {
total: number;
}

/**
* Where a room key came from
*/
export enum RoomKeySource {
/** from key backup */
Backup = "backup",
/** from a key export */
Export = "export",
/** via a key forward */
Forward = "forward",
/** directly from the sender */
Direct = "direct",
}

/**
* Options object for {@link CryptoApi#importRoomKeys}.
*/
Expand All @@ -577,7 +591,8 @@ export interface ImportRoomKeysOpts {
progressCallback?: (stage: ImportRoomKeyProgressData) => void;
// TODO, the rust SDK will always such imported keys as untrusted
untrusted?: boolean;
source?: String; // TODO: Enum (backup, file, ??)
/** Where the room key came from */
source?: RoomKeySource;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/algorithms/megolm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { EventType, MsgType, ToDeviceMessageId } from "../../@types/event";
import { IMegolmEncryptedContent, IncomingRoomKeyRequest, IEncryptedContent } from "../index";
import { RoomKeyRequestState } from "../OutgoingRoomKeyRequestManager";
import { OlmGroupSessionExtraData } from "../../@types/crypto";
import { RoomKeySource } from "../../crypto-api";
import { MatrixError } from "../../http-api";
import { immediate, MapWithDefault } from "../../utils";

Expand Down Expand Up @@ -2046,7 +2047,7 @@ export class MegolmDecryption extends DecryptionAlgorithm {
extraSessionData,
)
.then(() => {
if (source !== "backup") {
if (source !== RoomKeySource.Backup) {
// don't wait for it to complete
this.crypto.backupManager.backupGroupSession(session.sender_key, session.session_id).catch((e) => {
// This throws if the upload failed, but this is fine
Expand Down
22 changes: 18 additions & 4 deletions src/rust-crypto/rust-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
KeyBackupCheck,
KeyBackupInfo,
KeyBackupSession,
RoomKeySource,
UserVerificationStatus,
VerificationRequest,
} from "../crypto-api";
Expand Down Expand Up @@ -223,7 +224,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
for (const k of keys) {
k.room_id = targetRoomId;
}
await this.importRoomKeys(keys);
await this.importRoomKeys(keys, { source: RoomKeySource.Backup });
}

/**
Expand Down Expand Up @@ -390,16 +391,29 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv

public async importRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void> {
// TODO when backup support will be added we would need to expose the `from_backup` flag in the bindings
const jsonKeys = JSON.stringify(keys);
await this.olmMachine.importRoomKeys(jsonKeys, (progress: BigInt, total: BigInt) => {
const callback = (progress: BigInt, total: BigInt) => {
const importOpt: ImportRoomKeyProgressData = {
total: Number(total),
successes: Number(progress),
stage: "load_keys",
failures: 0,
};
opts?.progressCallback?.(importOpt);
});
};
if (opts?.source === RoomKeySource.Backup) {
const keysByRoom: Map<RustSdkCryptoJs.RoomId, Map<string, IMegolmSessionData>> = new Map();
for (const key of keys) {
let room_id = new RustSdkCryptoJs.RoomId(key.room_id);
if (!keysByRoom.has(room_id)) {
keysByRoom.set(room_id, new Map());
}
keysByRoom.get(room_id)!.set(key.session_id, key);
}
await this.olmMachine.importBackedUpRoomKeys(keysByRoom, callback);
} else {
const jsonKeys = JSON.stringify(keys);
await this.olmMachine.importExportedRoomKeys(jsonKeys, callback);
}
}

/**
Expand Down

0 comments on commit 0a24d42

Please sign in to comment.