Cable-Desktop/libtextsecure/axolotl_wrapper.js
lilia f3f084398f Handle identity key errors when retrying decrypt
After setting a new identity key as trusted, we retry decryption on all
pending conflicts for that contact. If their identity changed twice in a
row, we can still get a conflict the second time, and should handle it
appropriately.
2015-07-31 17:28:25 -07:00

76 lines
3.2 KiB
JavaScript

;(function() {
'use strict';
window.textsecure = window.textsecure || {};
window.textsecure.storage = window.textsecure.storage || {};
textsecure.storage.axolotl = new AxolotlStore();
var axolotlInstance = axolotl.protocol(textsecure.storage.axolotl);
window.textsecure = window.textsecure || {};
window.textsecure.protocol_wrapper = {
decrypt: function(source, sourceDevice, type, blob) {
if (sourceDevice === null) { sourceDevice = 0; }
var fromAddress = [source, sourceDevice].join('.');
switch(type) {
case textsecure.protobuf.Envelope.Type.CIPHERTEXT:
return axolotlInstance.decryptWhisperMessage(fromAddress, getString(blob));
case textsecure.protobuf.Envelope.Type.PREKEY_BUNDLE:
if (blob.readUint8() != ((3 << 4) | 3))
throw new Error("Bad version byte");
var blob = blob.toArrayBuffer();
return axolotlInstance.handlePreKeyWhisperMessage(fromAddress, blob).catch(function(e) {
handleIdentityKeyError(fromAddress, blob, e);
});
default:
return new Promise.reject(new Error("Unknown message type"));
}
},
closeOpenSessionForDevice: function(encodedNumber) {
return axolotlInstance.closeOpenSessionForDevice(encodedNumber)
},
encryptMessageFor: function(deviceObject, pushMessageContent) {
return axolotlInstance.encryptMessageFor(deviceObject, pushMessageContent);
},
startWorker: function() {
axolotlInstance.startWorker('/js/libaxolotl-worker.js');
},
stopWorker: function() {
axolotlInstance.stopWorker();
},
createIdentityKeyRecvSocket: function() {
return axolotlInstance.createIdentityKeyRecvSocket();
},
hasOpenSession: function(encodedNumber) {
return axolotlInstance.hasOpenSession(encodedNumber);
},
getRegistrationId: function(encodedNumber) {
return axolotlInstance.getRegistrationId(encodedNumber);
}
};
function handleIdentityKeyError(from, blob, e) {
if (e.message === 'Unknown identity key') {
// create an error that the UI will pick up and ask the
// user if they want to re-negotiate
throw new textsecure.IncomingIdentityKeyError(from, blob, e.identityKey);
}
throw e;
}
var tryMessageAgain = function(from, encodedMessage) {
return axolotlInstance.handlePreKeyWhisperMessage(from, encodedMessage).then(function(res) {
var finalMessage = textsecure.protobuf.DataMessage.decode(res[0]);
if ((finalMessage.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION)
== textsecure.protobuf.DataMessage.Flags.END_SESSION &&
finalMessage.sync !== null)
res[1]();
return processDecrypted(finalMessage);
}).catch(function(e) {
handleIdentityKeyError(from, encodedMessage, e);
});
};
textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.INIT_SESSION);
})();