1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-23 17:02:25 +03:00

Add crypto mode setting for invisible crypto, and apply it to decrypting events (#4407)

Adds a global "crypto mode" setting to the crypto API (only works with Rust crypto), and changes the decryption settings based on that.
This commit is contained in:
Hubert Chathi
2024-09-18 07:53:07 -04:00
committed by GitHub
parent 414ac9d8cc
commit dbb4828eda
6 changed files with 210 additions and 36 deletions

View File

@@ -45,6 +45,7 @@ import {
CrossSigningStatus,
CryptoApi,
CryptoCallbacks,
CryptoMode,
Curve25519AuthData,
DecryptionFailureCode,
DeviceVerificationStatus,
@@ -106,6 +107,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
private readonly RECOVERY_KEY_DERIVATION_ITERATIONS = 500000;
private _trustCrossSignedDevices = true;
private cryptoMode = CryptoMode.Legacy;
/** whether {@link stop} has been called */
private stopped = false;
@@ -257,7 +259,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
// through decryptEvent and hence get rid of this case.
throw new Error("to-device event was not decrypted in preprocessToDeviceMessages");
}
return await this.eventDecryptor.attemptEventDecryption(event);
return await this.eventDecryptor.attemptEventDecryption(event, this.cryptoMode);
}
/**
@@ -367,6 +369,13 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
return `Rust SDK ${versions.matrix_sdk_crypto} (${versions.git_sha}), Vodozemac ${versions.vodozemac}`;
}
/**
* Implementation of {@link Crypto.CryptoApi#setCryptoMode}.
*/
public setCryptoMode(cryptoMode: CryptoMode): void {
this.cryptoMode = cryptoMode;
}
/**
* Implementation of {@link CryptoApi#isEncryptionEnabledInRoom}.
*/
@@ -1742,18 +1751,31 @@ class EventDecryptor {
private readonly perSessionBackupDownloader: PerSessionKeyBackupDownloader,
) {}
public async attemptEventDecryption(event: MatrixEvent): Promise<IEventDecryptionResult> {
public async attemptEventDecryption(event: MatrixEvent, cryptoMode: CryptoMode): Promise<IEventDecryptionResult> {
// add the event to the pending list *before* attempting to decrypt.
// then, if the key turns up while decryption is in progress (and
// decryption fails), we will schedule a retry.
// (fixes https://github.com/vector-im/element-web/issues/5001)
this.addEventToPendingList(event);
let trustRequirement;
switch (cryptoMode) {
case CryptoMode.Legacy:
trustRequirement = RustSdkCryptoJs.TrustRequirement.Untrusted;
break;
case CryptoMode.Transition:
trustRequirement = RustSdkCryptoJs.TrustRequirement.CrossSignedOrLegacy;
break;
case CryptoMode.Invisible:
trustRequirement = RustSdkCryptoJs.TrustRequirement.CrossSigned;
break;
}
try {
const res = (await this.olmMachine.decryptRoomEvent(
stringifyEvent(event),
new RustSdkCryptoJs.RoomId(event.getRoomId()!),
new RustSdkCryptoJs.DecryptionSettings(RustSdkCryptoJs.TrustRequirement.Untrusted),
new RustSdkCryptoJs.DecryptionSettings(trustRequirement),
)) as RustSdkCryptoJs.DecryptedRoomEvent;
// Success. We can remove the event from the pending list, if
@@ -1861,6 +1883,36 @@ class EventDecryptor {
errorDetails,
);
case RustSdkCryptoJs.DecryptionErrorCode.SenderIdentityPreviouslyVerified:
// We're refusing to decrypt due to not trusting the sender,
// rather than failing to decrypt due to lack of keys, so we
// don't need to keep it on the pending list.
this.removeEventFromPendingList(event);
throw new DecryptionError(
DecryptionFailureCode.SENDER_IDENTITY_PREVIOUSLY_VERIFIED,
"The sender identity is unverified, but was previously verified.",
);
case RustSdkCryptoJs.DecryptionErrorCode.UnknownSenderDevice:
// We're refusing to decrypt due to not trusting the sender,
// rather than failing to decrypt due to lack of keys, so we
// don't need to keep it on the pending list.
this.removeEventFromPendingList(event);
throw new DecryptionError(
DecryptionFailureCode.UNKNOWN_SENDER_DEVICE,
"The sender device is not known.",
);
case RustSdkCryptoJs.DecryptionErrorCode.UnsignedSenderDevice:
// We're refusing to decrypt due to not trusting the sender,
// rather than failing to decrypt due to lack of keys, so we
// don't need to keep it on the pending list.
this.removeEventFromPendingList(event);
throw new DecryptionError(
DecryptionFailureCode.UNSIGNED_SENDER_DEVICE,
"The sender identity is not cross-signed.",
);
// We don't map MismatchedIdentityKeys for now, as there is no equivalent in legacy.
// Just put it on the `UNKNOWN_ERROR` bucket.
default: