diff --git a/spec/unit/rust-crypto/verification.spec.ts b/spec/unit/rust-crypto/verification.spec.ts index 90f9e846b32..6bf3df1a026 100644 --- a/spec/unit/rust-crypto/verification.spec.ts +++ b/spec/unit/rust-crypto/verification.spec.ts @@ -62,9 +62,13 @@ describe("VerificationRequest", () => { describe("startVerification", () => { let request: RustVerificationRequest; + let machine: Mocked; + let inner: Mocked; beforeEach(() => { - request = makeTestRequest(); + inner = makeMockedInner(); + machine = { getDevice: jest.fn() } as unknown as Mocked; + request = makeTestRequest(inner, machine); }); it("does not permit methods other than SAS", async () => { @@ -73,7 +77,15 @@ describe("VerificationRequest", () => { ); }); + it("raises an error if the other device is unknown", async () => { + await expect(request.startVerification("m.sas.v1")).rejects.toThrow( + "startVerification(): other device is unknown", + ); + }); + it("raises an error if starting verification does not produce a verifier", async () => { + jest.spyOn(inner, "otherDeviceId", "get").mockReturnValue(new RustSdkCryptoJs.DeviceId("other_device")); + machine.getDevice.mockResolvedValue({} as RustSdkCryptoJs.Device); await expect(request.startVerification("m.sas.v1")).rejects.toThrow( "Still no verifier after startSas() call", ); @@ -118,11 +130,13 @@ describe("isVerificationEvent", () => { /** build a RustVerificationRequest with default parameters */ function makeTestRequest( inner?: RustSdkCryptoJs.VerificationRequest, + olmMachine?: RustSdkCryptoJs.OlmMachine, outgoingRequestProcessor?: OutgoingRequestProcessor, ): RustVerificationRequest { inner ??= makeMockedInner(); + olmMachine ??= {} as RustSdkCryptoJs.OlmMachine; outgoingRequestProcessor ??= {} as OutgoingRequestProcessor; - return new RustVerificationRequest(inner, outgoingRequestProcessor, []); + return new RustVerificationRequest(olmMachine, inner, outgoingRequestProcessor, []); } /** Mock up a rust-side VerificationRequest */ @@ -133,5 +147,8 @@ function makeMockedInner(): Mocked { phase: jest.fn().mockReturnValue(RustSdkCryptoJs.VerificationRequestPhase.Created), isPassive: jest.fn().mockReturnValue(false), timeRemainingMillis: jest.fn(), + get otherDeviceId() { + return undefined; + }, } as unknown as Mocked; } diff --git a/src/rust-crypto/rust-crypto.ts b/src/rust-crypto/rust-crypto.ts index de7b368b4eb..c32662a0f69 100644 --- a/src/rust-crypto/rust-crypto.ts +++ b/src/rust-crypto/rust-crypto.ts @@ -940,6 +940,7 @@ export class RustCrypto extends TypedEventEmitter new RustVerificationRequest( + this.olmMachine, request, this.outgoingRequestProcessor, this._supportedVerificationMethods, @@ -970,6 +971,7 @@ export class RustCrypto extends TypedEventEmitter { + const otherDeviceId = this.inner.otherDeviceId; + if (!otherDeviceId) { + return undefined; + } + return await this.olmMachine.getDevice(this.inner.otherUserId, otherDeviceId, 5); + } + /** True if the other party in this request is one of this user's own devices. */ public get isSelfVerification(): boolean { return this.inner.isSelfVerification(); @@ -322,6 +333,11 @@ export class RustVerificationRequest throw new Error(`Unsupported verification method ${method}`); } + // make sure that we have a list of the other user's devices (workaround https://github.com/matrix-org/matrix-rust-sdk/issues/2896) + if (!(await this.getOtherDevice())) { + throw new Error("startVerification(): other device is unknown"); + } + const res: | [RustSdkCryptoJs.Sas, RustSdkCryptoJs.RoomMessageRequest | RustSdkCryptoJs.ToDeviceRequest] | undefined = await this.inner.startSas(); @@ -392,6 +408,11 @@ export class RustVerificationRequest * Implementation of {@link Crypto.VerificationRequest#generateQRCode}. */ public async generateQRCode(): Promise { + // make sure that we have a list of the other user's devices (workaround https://github.com/matrix-org/matrix-rust-sdk/issues/2896) + if (!(await this.getOtherDevice())) { + throw new Error("generateQRCode(): other device is unknown"); + } + const innerVerifier: RustSdkCryptoJs.Qr | undefined = await this.inner.generateQrCode(); // If we are unable to generate a QRCode, we return undefined if (!innerVerifier) return;