From 73c9f4e32239e09bc14d5bb55672bd94a6fc1dc0 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Thu, 27 Jul 2023 13:16:10 +0100 Subject: [PATCH] Add `CryptoApi.setDeviceVerified` (#3624) I need a way to mark devices as trusted for the backup tests. --- spec/unit/rust-crypto/rust-crypto.spec.ts | 56 +++++++++++++++++++++++ src/crypto-api.ts | 16 +++++++ src/crypto/index.ts | 9 ++++ src/rust-crypto/rust-crypto.ts | 17 +++++++ 4 files changed, 98 insertions(+) diff --git a/spec/unit/rust-crypto/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts index 52a69c3e0..0173af410 100644 --- a/spec/unit/rust-crypto/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -23,6 +23,8 @@ import { RustCrypto } from "../../../src/rust-crypto/rust-crypto"; import { initRustCrypto } from "../../../src/rust-crypto"; import { CryptoEvent, + Device, + DeviceVerification, HttpApiEvent, HttpApiEventHandlerMap, IHttpOpts, @@ -351,6 +353,60 @@ describe("RustCrypto", () => { }); }); + describe("setDeviceVerified", () => { + let rustCrypto: RustCrypto; + + async function getTestDevice(): Promise { + const devices = await rustCrypto.getUserDeviceInfo([testData.TEST_USER_ID]); + return devices.get(testData.TEST_USER_ID)!.get(testData.TEST_DEVICE_ID)!; + } + + beforeEach(async () => { + rustCrypto = await makeTestRustCrypto( + new MatrixHttpApi(new TypedEventEmitter(), { + baseUrl: "http://server/", + prefix: "", + onlyData: true, + }), + testData.TEST_USER_ID, + ); + + fetchMock.post("path:/_matrix/client/v3/keys/upload", { one_time_key_counts: {} }); + fetchMock.post("path:/_matrix/client/v3/keys/query", { + device_keys: { + [testData.TEST_USER_ID]: { + [testData.TEST_DEVICE_ID]: testData.SIGNED_TEST_DEVICE_DATA, + }, + }, + }); + // call onSyncCompleted to kick off the outgoingRequestLoop and download the device list. + rustCrypto.onSyncCompleted({}); + + // before the call, the device should be unverified. + const device = await getTestDevice(); + expect(device.verified).toEqual(DeviceVerification.Unverified); + }); + + it("should throw an error for an unknown device", async () => { + await expect(rustCrypto.setDeviceVerified(testData.TEST_USER_ID, "xxy")).rejects.toThrow("Unknown device"); + }); + + it("should mark an unverified device as verified", async () => { + await rustCrypto.setDeviceVerified(testData.TEST_USER_ID, testData.TEST_DEVICE_ID); + + // and confirm that the device is now verified + expect((await getTestDevice()).verified).toEqual(DeviceVerification.Verified); + }); + + it("should mark a verified device as unverified", async () => { + await rustCrypto.setDeviceVerified(testData.TEST_USER_ID, testData.TEST_DEVICE_ID); + expect((await getTestDevice()).verified).toEqual(DeviceVerification.Verified); + + await rustCrypto.setDeviceVerified(testData.TEST_USER_ID, testData.TEST_DEVICE_ID, false); + expect((await getTestDevice()).verified).toEqual(DeviceVerification.Unverified); + }); + }); + describe("getDeviceVerificationStatus", () => { let rustCrypto: RustCrypto; let olmMachine: Mocked; diff --git a/src/crypto-api.ts b/src/crypto-api.ts index 9045cfe05..75bf2a8c4 100644 --- a/src/crypto-api.ts +++ b/src/crypto-api.ts @@ -137,6 +137,22 @@ export interface CryptoApi { */ getDeviceVerificationStatus(userId: string, deviceId: string): Promise; + /** + * Mark the given device as locally verified. + * + * Marking a devices as locally verified has much the same effect as completing the verification dance, or receiving + * a cross-signing signature for it. + * + * @param userId - owner of the device + * @param deviceId - unique identifier for the device. + * @param verified - whether to mark the device as verified. Defaults to 'true'. + * + * @throws an error if the device is unknown, or has not published any encryption keys. + * + * @remarks Fires {@link CryptoEvent#DeviceVerificationChanged} + */ + setDeviceVerified(userId: string, deviceId: string, verified?: boolean): Promise; + /** * Checks whether cross signing: * - is enabled on this account and trusted by this device diff --git a/src/crypto/index.ts b/src/crypto/index.ts index ab588afce..8ebc1bb07 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -2174,6 +2174,15 @@ export class Crypto extends TypedEventEmitter { + await this.setDeviceVerification(userId, deviceId, verified); + } + /** * Update the blocked/verified state of the given device * diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index a900e21a9..f2731e497 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -377,6 +377,23 @@ export class RustCrypto extends TypedEventEmitter { + const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice( + new RustSdkCryptoJs.UserId(userId), + new RustSdkCryptoJs.DeviceId(deviceId), + ); + + if (!device) { + throw new Error(`Unknown device ${userId}|${deviceId}`); + } + await device.setLocalTrust(verified ? RustSdkCryptoJs.LocalTrust.Verified : RustSdkCryptoJs.LocalTrust.Unset); + } + /** * Implementation of {@link CryptoApi#getDeviceVerificationStatus}. */