Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Element-R: emit VerificationRequestReceived on incoming request #3762

Merged
merged 3 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 40 additions & 10 deletions spec/integ/crypto/verification.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -980,12 +980,43 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st
});
}

it("Verification request not found", async () => {
// Expect to not find any verification request
const request = aliceClient.getCrypto()!.findVerificationRequestDMInProgress(TEST_ROOM_ID, "@bob:xyz");
expect(request).toBeUndefined();
});

it("ignores old verification requests", async () => {
const eventHandler = jest.fn();
aliceClient.on(CryptoEvent.VerificationRequestReceived, eventHandler);

const verificationRequestEvent = createVerificationRequestEvent();
verificationRequestEvent.origin_server_ts -= 1000000;
returnRoomMessageFromSync(TEST_ROOM_ID, verificationRequestEvent);

await syncPromise(aliceClient);

// make sure the event has arrived
const room = aliceClient.getRoom(TEST_ROOM_ID)!;
const matrixEvent = room.getLiveTimeline().getEvents()[0];
expect(matrixEvent.getId()).toEqual(verificationRequestEvent.event_id);

// check that an event has not been raised, and that the request is not found
expect(eventHandler).not.toHaveBeenCalled();
expect(
aliceClient.getCrypto()!.findVerificationRequestDMInProgress(TEST_ROOM_ID, "@bob:xyz"),
).not.toBeDefined();
});

it("Plaintext verification request from Bob to Alice", async () => {
// Add verification request from Bob to Alice in the DM between them
returnRoomMessageFromSync(TEST_ROOM_ID, createVerificationRequestEvent());

// Wait for the sync response to be processed
await syncPromise(aliceClient);
// Wait for the request to be received
const request1 = await emitPromise(aliceClient, CryptoEvent.VerificationRequestReceived);
expect(request1.roomId).toBe(TEST_ROOM_ID);
expect(request1.isSelfVerification).toBe(false);
expect(request1.otherUserId).toBe("@bob:xyz");

const request = aliceClient.getCrypto()!.findVerificationRequestDMInProgress(TEST_ROOM_ID, "@bob:xyz");
// Expect to find the verification request received during the sync
Expand All @@ -994,12 +1025,6 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st
expect(request?.otherUserId).toBe("@bob:xyz");
});

it("Verification request not found", async () => {
// Expect to not find any verification request
const request = aliceClient.getCrypto()!.findVerificationRequestDMInProgress(TEST_ROOM_ID, "@bob:xyz");
expect(request).not.toBeDefined();
});

it("Encrypted verification request from Bob to Alice", async () => {
const p2pSession = await createOlmSession(testOlmAccount, e2eKeyReceiver);
const groupSession = new Olm.OutboundGroupSession();
Expand All @@ -1021,14 +1046,19 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("verification (%s)", (backend: st
await awaitDecryption(matrixEvent);
expect(matrixEvent.getContent().msgtype).toEqual("m.bad.encrypted");

const requestEventPromise = emitPromise(aliceClient, CryptoEvent.VerificationRequestReceived);

// Send Bob the room keys
returnToDeviceMessageFromSync(toDeviceEvent);

// advance the clock, because the devicelist likes to sleep for 5ms during key downloads
await jest.advanceTimersByTimeAsync(10);

// Wait for the message to be decrypted
await awaitDecryption(matrixEvent, { waitOnDecryptionFailure: true });
// Wait for the request to be decrypted
const request1 = await requestEventPromise;
expect(request1.roomId).toBe(TEST_ROOM_ID);
expect(request1.isSelfVerification).toBe(false);
expect(request1.otherUserId).toBe("@bob:xyz");

const request = aliceClient.getCrypto()!.findVerificationRequestDMInProgress(TEST_ROOM_ID, "@bob:xyz");
// Expect to find the verification request received during the sync
Expand Down
28 changes: 27 additions & 1 deletion src/rust-crypto/rust-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ import { keyFromPassphrase } from "../crypto/key_passphrase";
import { encodeRecoveryKey } from "../crypto/recoverykey";
import { crypto } from "../crypto/crypto";
import { isVerificationEvent, RustVerificationRequest, verificationMethodIdentifierToMethod } from "./verification";
import { EventType } from "../@types/event";
import { EventType, MsgType } from "../@types/event";
import { CryptoEvent } from "../crypto";
import { TypedEventEmitter } from "../models/typed-event-emitter";
import { RustBackupCryptoEventMap, RustBackupCryptoEvents, RustBackupDecryptor, RustBackupManager } from "./backup";
Expand Down Expand Up @@ -1407,6 +1407,32 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
new RustSdkCryptoJs.RoomId(roomId),
);

if (
event.getType() === EventType.RoomMessage &&
event.getContent().msgtype === MsgType.KeyVerificationRequest
) {
const request: RustSdkCryptoJs.VerificationRequest | undefined = this.olmMachine.getVerificationRequest(
new RustSdkCryptoJs.UserId(event.getSender()!),
event.getId()!,
);

if (!request) {
// There are multiple reasons this can happen; probably the most likely is that the event is too old.
logger.info(
`Ignoring just-received verification request ${event.getId()} which did not start a rust-side verification`,
);
} else {
this.emit(
CryptoEvent.VerificationRequestReceived,
new RustVerificationRequest(
request,
this.outgoingRequestProcessor,
this._supportedVerificationMethods,
),
);
}
}

// that may have caused us to queue up outgoing requests, so make sure we send them.
this.outgoingRequestLoop();
}
Expand Down
Loading