diff --git a/spec/unit/crypto/algorithms/megolm.spec.js b/spec/unit/crypto/algorithms/megolm.spec.js index e629385a0..c2646c726 100644 --- a/spec/unit/crypto/algorithms/megolm.spec.js +++ b/spec/unit/crypto/algorithms/megolm.spec.js @@ -598,6 +598,7 @@ describe("MegolmDecryption", function() { aliceClient.initCrypto(), bobClient.initCrypto(), ]); + aliceClient._crypto.downloadKeys = async () => {}; const bobDevice = bobClient._crypto._olmDevice; const roomId = "!someroom"; @@ -649,6 +650,7 @@ describe("MegolmDecryption", function() { bobClient.initCrypto(), ]); const bobDevice = bobClient._crypto._olmDevice; + aliceClient._crypto.downloadKeys = async () => {}; const roomId = "!someroom"; diff --git a/src/crypto/algorithms/megolm.js b/src/crypto/algorithms/megolm.js index 8c9ef81f0..b74a856a3 100644 --- a/src/crypto/algorithms/megolm.js +++ b/src/crypto/algorithms/megolm.js @@ -1260,17 +1260,25 @@ MegolmDecryption.prototype.onRoomKeyWithheldEvent = async function(event) { this.retryDecryptionFromSender(senderKey); return; } - const device = this._crypto._deviceList.getDeviceByIdentityKey( + let device = this._crypto._deviceList.getDeviceByIdentityKey( content.algorithm, senderKey, ); if (!device) { - logger.info( - "Couldn't find device for identity key " + senderKey + - ": not establishing session", + // if we don't know about the device, fetch the user's devices again + // and retry before giving up + await this._crypto.downloadKeys([sender], false); + device = this._crypto._deviceList.getDeviceByIdentityKey( + content.algorithm, senderKey, ); - await this._olmDevice.recordSessionProblem(senderKey, "no_olm", false); - this.retryDecryptionFromSender(senderKey); - return; + if (!device) { + logger.info( + "Couldn't find device for identity key " + senderKey + + ": not establishing session", + ); + await this._olmDevice.recordSessionProblem(senderKey, "no_olm", false); + this.retryDecryptionFromSender(senderKey); + return; + } } await olmlib.ensureOlmSessionsForDevices( this._olmDevice, this._baseApis, {[sender]: [device]}, false, diff --git a/src/crypto/index.js b/src/crypto/index.js index 90adf8a01..b59cdf895 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -2723,15 +2723,21 @@ Crypto.prototype._onToDeviceBadEncrypted = async function(event) { // on a current session. // Note that an undecryptable message from another device could easily be spoofed - // is there anything we can do to mitigate this? - const device = this._deviceList.getDeviceByIdentityKey(algorithm, deviceKey); + let device = this._deviceList.getDeviceByIdentityKey(algorithm, deviceKey); if (!device) { - logger.info( - "Couldn't find device for identity key " + deviceKey + - ": not re-establishing session", - ); - await this._olmDevice.recordSessionProblem(deviceKey, "wedged", false); - retryDecryption(); - return; + // if we don't know about the device, fetch the user's devices again + // and retry before giving up + await this.downloadKeys([sender], false); + device = this._deviceList.getDeviceByIdentityKey(algorithm, deviceKey); + if (!device) { + logger.info( + "Couldn't find device for identity key " + deviceKey + + ": not re-establishing session", + ); + await this._olmDevice.recordSessionProblem(deviceKey, "wedged", false); + retryDecryption(); + return; + } } const devicesByUser = {}; devicesByUser[sender] = [device];