1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-13 19:42:25 +03:00

Check recipient and sender in Olm messages

Embed the sender, recipient, and recipient keys in the plaintext of Olm
messages, and check those fields on receipt.

Fixes https://github.com/vector-im/vector-web/issues/2483
This commit is contained in:
Richard van der Hoff
2016-10-19 11:24:59 +01:00
parent c5d738d25c
commit b5c7c700d5
7 changed files with 241 additions and 65 deletions

View File

@@ -95,32 +95,43 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) {
var self = this;
return this._ensureSession(users).then(function() {
var participantKeys = [];
var payloadFields = {
room_id: room.roomId,
type: eventType,
content: content,
};
var encryptedContent = {
algorithm: olmlib.OLM_ALGORITHM,
sender_key: self._olmDevice.deviceCurve25519Key,
ciphertext: {},
};
for (var i = 0; i < users.length; ++i) {
var userId = users[i];
var devices = self._crypto.getStoredDevicesForUser(userId);
for (var j = 0; j < devices.length; ++j) {
var deviceInfo = devices[j];
var key = deviceInfo.getIdentityKey();
if (key == self._olmDevice.deviceCurve25519Key) {
// don't bother setting up session to ourself
// don't bother sending to ourself
continue;
}
if (deviceInfo.verified == DeviceVerification.BLOCKED) {
// don't bother setting up sessions with blocked users
continue;
}
participantKeys.push(key);
olmlib.encryptMessageForDevice(
encryptedContent.ciphertext,
self._userId, self._deviceId, self._olmDevice,
userId, deviceInfo, payloadFields
);
}
}
return olmlib.encryptMessageForDevices(
self._deviceId, self._olmDevice, participantKeys, {
room_id: room.roomId,
type: eventType,
content: content,
}
);
return encryptedContent;
});
};
@@ -173,10 +184,70 @@ OlmDecryption.prototype.decryptEvent = function(event) {
throw new base.DecryptionError("Bad Encrypted Message");
}
// TODO: Check the sender user id matches the sender key.
// TODO: check the room_id and fingerprint
var payload = JSON.parse(payloadString);
// check that we were the intended recipient, to avoid unknown-key attack
// https://github.com/vector-im/vector-web/issues/2483
if (payload.recipient === undefined) {
// older versions of riot did not set this field, so we cannot make
// this check. TODO: kill this off once our users have updated
console.warn(
"Olm event (id=" + event.event_id + ") contains no 'recipient' " +
"property; cannot prevent unknown-key attack");
} else if (payload.recipient != this._userId) {
console.warn(
"Event " + event.event_id + ": Intended recipient " +
payload.recipient + " does not match our id " + this._userId
);
throw new base.DecryptionError(
"Message was intented for " + payload.recipient
);
}
if (payload.recipient_keys === undefined) {
// ditto
console.warn(
"Olm event (id=" + event.event_id + ") contains no " +
"'recipient_keys' property; cannot prevent unknown-key attack");
} else if (payload.recipient_keys.ed25519 !=
this._olmDevice.deviceEd25519Key) {
console.warn(
"Event " + event.event_id + ": Intended recipient ed25519 key " +
payload.recipient_keys.ed25519 + " did not match ours"
);
throw new base.DecryptionError("Message not intended for this device");
}
// check that the original sender matches what the homeserver told us, to
// avoid people masquerading as others.
// (this check is also provided via the sender's embedded ed25519 key,
// which is checked elsewhere).
if (payload.sender === undefined) {
// ditto
console.warn(
"Olm event (id=" + event.event_id + ") contains no " +
"'sender' property; cannot prevent unknown-key attack");
} else if (payload.sender != event.sender) {
console.warn(
"Event " + event.event_id + ": original sender " + payload.sender +
" does not match reported sender " + event.sender
);
throw new base.DecryptionError(
"Message forwarded from " + payload.sender
);
}
// Olm events intended for a room have a room_id.
if (payload.room_id !== event.room_id) {
console.warn(
"Event " + event.event_id + ": original room " + payload.room_id +
" does not match reported room " + event.room_id
);
throw new base.DecryptionError(
"Message intended for room " + payload.room_id
);
}
return {
payload: payload,
sessionExists: true,