diff options
author | Alexey Andreyev <aa13q@ya.ru> | 2019-08-23 17:14:09 +0300 |
---|---|---|
committer | Alexey Andreev <aa13q@ya.ru> | 2020-02-25 17:57:32 +0300 |
commit | 715a0c0aa094eedbe24516e19a7b37dde71ba994 (patch) | |
tree | 332f95145eaf3a1ae9315a72ad62e9986bf4d676 | |
parent | 3c293b287466e8de188fc62e73efc4730ab4dd31 (diff) | |
download | libquotient-715a0c0aa094eedbe24516e19a7b37dde71ba994.tar.gz libquotient-715a0c0aa094eedbe24516e19a7b37dde71ba994.zip |
E2EE: add connection session decrypt, handle to-device and device_one_time_keys_count
Signed-off-by: Alexey Andreev <aa13q@ya.ru>
-rw-r--r-- | lib/connection.cpp | 112 | ||||
-rw-r--r-- | lib/room.cpp | 5 | ||||
-rw-r--r-- | lib/room.h | 2 |
3 files changed, 119 insertions, 0 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index 75c459d5..98c8a4bc 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -43,6 +43,8 @@ #include "jobs/mediathumbnailjob.h" #include "jobs/syncjob.h" +#include "account.h" // QtOlm + #include <QtCore/QCoreApplication> #include <QtCore/QDir> #include <QtCore/QElapsedTimer> @@ -148,6 +150,65 @@ public: { return q->stateCacheDir().filePath("state.json"); } + + RoomEventPtr sessionDecryptMessage(const EncryptedEvent& encryptedEvent) + { + if (encryptedEvent.algorithm() != OlmV1Curve25519AesSha2AlgoKey) + { + return {}; + } + QString identityKey = + encryptionManager->account()->curve25519IdentityKey(); + QJsonObject personalCipherObject = + encryptedEvent.ciphertext(identityKey); + if (personalCipherObject.isEmpty()) { + qCDebug(E2EE) << "Encrypted event is not for the current device"; + return {}; + } + QString decrypted = encryptionManager->sessionDecryptMessage( + personalCipherObject, encryptedEvent.senderKey().toLatin1()); + if (decrypted.isEmpty()) { + qCDebug(E2EE) << "Problem with new session from senderKey:" + << encryptedEvent.senderKey() + << encryptionManager->account()->oneTimeKeys(); + return {}; + } + + RoomEventPtr decryptedEvent = makeEvent<RoomMessageEvent>( + QJsonDocument::fromJson(decrypted.toUtf8()).object()); + + if (decryptedEvent->senderId() != encryptedEvent.senderId()) { + qCDebug(E2EE) << "Found user" << decryptedEvent->senderId() + << "instead of sender" << encryptedEvent.senderId() + << "in Olm plaintext"; + return {}; + } + + // TODO: keys to constants + QJsonObject decryptedEventObject = decryptedEvent->fullJson(); + QString recipient = + decryptedEventObject.value("recipient"_ls).toString(); + if (recipient != data->userId()) { + qCDebug(E2EE) << "Found user" << recipient << "instead of us" + << data->userId() << "in Olm plaintext"; + return {}; + } + QString ourKey = decryptedEventObject.value("recipient_keys"_ls) + .toObject() + .value(Ed25519Key) + .toString(); + if (ourKey + != QString::fromUtf8( + encryptionManager->account()->ed25519IdentityKey())) { + qCDebug(E2EE) << "Found key" << ourKey + << "instead of ours own ed25519 key" + << encryptionManager->account()->ed25519IdentityKey() + << "in Olm plaintext"; + return {}; + } + + return decryptedEvent; + } }; Connection::Connection(const QUrl& server, QObject* parent) @@ -533,6 +594,57 @@ void Connection::onSyncSuccess(SyncData&& data, bool fromCache) d->dcLocalAdditions.clear(); d->dcLocalRemovals.clear(); } + // handling m.room_key to-device encrypted event + for (auto&& toDeviceEvent : data.takeToDeviceEvents()) { + if (toDeviceEvent->type() == EncryptedEvent::typeId()) { + event_ptr_tt<EncryptedEvent> encryptedEvent = + makeEvent<EncryptedEvent>(toDeviceEvent->fullJson()); + if (encryptedEvent->algorithm() != OlmV1Curve25519AesSha2AlgoKey) { + qCDebug(E2EE) + << "Encrypted event" << encryptedEvent->id() << "algorithm" + << encryptedEvent->algorithm() << "is not supported"; + return; + } + + // TODO: full maintaining of the device keys + // with device_lists sync extention and /keys/query + qCDebug(E2EE) << "Getting device keys for the m.room_key sender:" + << encryptedEvent->senderId(); + // d->encryptionManager->updateDeviceKeys(); + + RoomEventPtr decryptedEvent = + d->sessionDecryptMessage(*encryptedEvent.get()); + // since we are waiting for the RoomKeyEvent: + event_ptr_tt<RoomKeyEvent> roomKeyEvent = + makeEvent<RoomKeyEvent>(decryptedEvent->fullJson()); + if (!roomKeyEvent) { + qCDebug(E2EE) << "Failed to decrypt olm event from user" + << encryptedEvent->senderId(); + return; + } + Room* detectedRoom = room(roomKeyEvent->roomId()); + if (!detectedRoom) { + qCDebug(E2EE) + << "Encrypted event room id" << encryptedEvent->roomId() + << "is not found at the connection"; + return; + } + detectedRoom->handleRoomKeyEvent(roomKeyEvent.get(), + encryptedEvent->senderKey()); + } + } + // handling device_one_time_keys_count + auto deviceOneTimeKeysCount = data.deviceOneTimeKeysCount(); + if (!d->encryptionManager) + { + qCDebug(E2EE) << "Encryption manager is not there yet"; + return; + } + if (!deviceOneTimeKeysCount.isEmpty()) + { + d->encryptionManager->updateOneTimeKeyCounts(this, + deviceOneTimeKeysCount); + } } void Connection::stopSync() diff --git a/lib/room.cpp b/lib/room.cpp index b29f6f48..45c1be8b 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -1233,6 +1233,11 @@ QString Room::decryptMessage(QByteArray cipher, const QString& senderKey, return decrypted; } +void Room::handleRoomKeyEvent(RoomKeyEvent *roomKeyEvent, QString senderKey) +{ + // TODO +} + int Room::joinedCount() const { return d->summary.joinedMemberCount.value_or(d->membersMap.size()); @@ -26,6 +26,7 @@ #include "events/accountdataevents.h" #include "events/encryptedevent.h" +#include "events/roomkeyevent.h" #include "events/roommessageevent.h" #include "events/roomcreateevent.h" #include "events/roomtombstoneevent.h" @@ -215,6 +216,7 @@ public: const QString& sessionId) const; QString decryptMessage(QByteArray cipher, const QString& senderKey, const QString& deviceId, const QString& sessionId); + void handleRoomKeyEvent(RoomKeyEvent* roomKeyEvent, QString senderKey); int joinedCount() const; int invitedCount() const; int totalMemberCount() const; |