From fb9d7dc22c74022b914b1964965ed6b8b850d831 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Mon, 7 Mar 2022 19:56:10 +0100 Subject: Store the device's ed25519 in the database --- lib/connection.cpp | 4 ++-- lib/connection.h | 2 +- lib/database.cpp | 7 ++++--- lib/database.h | 2 +- lib/room.cpp | 6 +++--- 5 files changed, 11 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 4abb77a5..11c81edf 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -2150,9 +2150,9 @@ UnorderedMap, QOlmInboundGroupSessionPtr> Connection return database()->loadMegolmSessions(room->id(), picklingMode()); } -void Connection::saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session) +void Connection::saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session, const QString& ed25519Key) { - database()->saveMegolmSession(room->id(), senderKey, session->sessionId(), session->pickle(picklingMode())); + database()->saveMegolmSession(room->id(), senderKey, session->sessionId(), ed25519Key, session->pickle(picklingMode())); } QStringList Connection::devicesForUser(User* user) const diff --git a/lib/connection.h b/lib/connection.h index 4a475319..a4986b06 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -318,7 +318,7 @@ public: QOlmAccount* olmAccount() const; Database* database(); UnorderedMap, QOlmInboundGroupSessionPtr> loadRoomMegolmSessions(Room* room); - void saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session); + void saveMegolmSession(Room* room, const QString& senderKey, QOlmInboundGroupSession* session, const QString& ed25519Key); #endif // Quotient_E2EE_ENABLED Q_INVOKABLE Quotient::SyncJob* syncJob() const; Q_INVOKABLE int millisToReconnect() const; diff --git a/lib/database.cpp b/lib/database.cpp index 84c93046..13b41a70 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -83,7 +83,7 @@ void Database::migrateTo1() transaction(); execute(QStringLiteral("CREATE TABLE accounts (pickle TEXT);")); execute(QStringLiteral("CREATE TABLE olm_sessions (senderKey TEXT, sessionId TEXT, pickle TEXT);")); - execute(QStringLiteral("CREATE TABLE inbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); + execute(QStringLiteral("CREATE TABLE inbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, ed25519Key TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE outbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE group_session_record_index (roomId TEXT, sessionId TEXT, i INTEGER, eventId TEXT, ts INTEGER);")); execute(QStringLiteral("CREATE TABLE tracked_users (matrixId TEXT);")); @@ -179,12 +179,13 @@ UnorderedMap, QOlmInboundGroupSessionPtr> Database:: return sessions; } -void Database::saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionId, const QByteArray& pickle) +void Database::saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionId, const QString& ed25519Key, const QByteArray& pickle) { - auto query = prepareQuery(QStringLiteral("INSERT INTO inbound_megolm_sessions(roomId, senderKey, sessionId, pickle) VALUES(:roomId, :senderKey, :sessionId, :pickle);")); + auto query = prepareQuery(QStringLiteral("INSERT INTO inbound_megolm_sessions(roomId, senderKey, sessionId, ed25519Key, pickle) VALUES(:roomId, :senderKey, :sessionId, :ed25519Key, :pickle);")); query.bindValue(":roomId", roomId); query.bindValue(":senderKey", senderKey); query.bindValue(":sessionId", sessionId); + query.bindValue(":ed25519Key", ed25519Key); query.bindValue(":pickle", pickle); transaction(); execute(query); diff --git a/lib/database.h b/lib/database.h index d4d5fb56..f6a491fb 100644 --- a/lib/database.h +++ b/lib/database.h @@ -30,7 +30,7 @@ public: void saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle); UnorderedMap> loadOlmSessions(const PicklingMode& picklingMode); UnorderedMap, QOlmInboundGroupSessionPtr> loadMegolmSessions(const QString& roomId, const PicklingMode& picklingMode); - void saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionKey, const QByteArray& pickle); + void saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionKey, const QString& ed25519Key, const QByteArray& pickle); void addGroupSessionIndexRecord(const QString& roomId, const QString& sessionId, uint32_t index, const QString& eventId, qint64 ts); std::pair groupSessionIndexRecord(const QString& roomId, const QString& sessionId, qint64 index); void clearRoomData(const QString& roomId); diff --git a/lib/room.cpp b/lib/room.cpp index 6197b3a2..88aa1d07 100644 --- a/lib/room.cpp +++ b/lib/room.cpp @@ -341,7 +341,7 @@ public: UnorderedMap, QOlmInboundGroupSessionPtr> groupSessions; bool addInboundGroupSession(QString senderKey, QString sessionId, - QString sessionKey) + QString sessionKey, QString ed25519Key) { if (groupSessions.find({senderKey, sessionId}) != groupSessions.end()) { qCWarning(E2EE) << "Inbound Megolm session" << sessionId @@ -356,7 +356,7 @@ public: return false; } qCWarning(E2EE) << "Adding inbound session"; - connection->saveMegolmSession(q, senderKey, megolmSession.get()); + connection->saveMegolmSession(q, senderKey, megolmSession.get(), ed25519Key); groupSessions[{senderKey, sessionId}] = std::move(megolmSession); return true; } @@ -1509,7 +1509,7 @@ void Room::handleRoomKeyEvent(const RoomKeyEvent& roomKeyEvent, << roomKeyEvent.algorithm() << "in m.room_key event"; } if (d->addInboundGroupSession(senderKey, roomKeyEvent.sessionId(), - roomKeyEvent.sessionKey())) { + roomKeyEvent.sessionKey(), roomKeyEvent.fullJson()["keys"]["ed25519"].toString())) { qCWarning(E2EE) << "added new inboundGroupSession:" << d->groupSessions.size(); for (const auto& eventId : d->undecryptedEvents[roomKeyEvent.sessionId()]) { -- cgit v1.2.3 From ce32dc09a9257ce5cb3188879f549d9b2fa816a1 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Mon, 7 Mar 2022 20:56:23 +0100 Subject: Add datbase migration --- lib/database.cpp | 12 +++++++++++- lib/database.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/database.cpp b/lib/database.cpp index 13b41a70..d070e1de 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -28,6 +28,7 @@ Database::Database(const QString& matrixId, const QString& deviceId, QObject* pa switch(version()) { case 0: migrateTo1(); + case 1: migrateTo2(); } } @@ -83,7 +84,7 @@ void Database::migrateTo1() transaction(); execute(QStringLiteral("CREATE TABLE accounts (pickle TEXT);")); execute(QStringLiteral("CREATE TABLE olm_sessions (senderKey TEXT, sessionId TEXT, pickle TEXT);")); - execute(QStringLiteral("CREATE TABLE inbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, ed25519Key TEXT, pickle TEXT);")); + execute(QStringLiteral("CREATE TABLE inbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE outbound_megolm_sessions (roomId TEXT, senderKey TEXT, sessionId TEXT, pickle TEXT);")); execute(QStringLiteral("CREATE TABLE group_session_record_index (roomId TEXT, sessionId TEXT, i INTEGER, eventId TEXT, ts INTEGER);")); execute(QStringLiteral("CREATE TABLE tracked_users (matrixId TEXT);")); @@ -94,6 +95,15 @@ void Database::migrateTo1() commit(); } +void Database::migrateTo2() +{ + qCDebug(DATABASE) << "Migrating database to version 2"; + transaction(); + execute(QStringLiteral("ALTER TABLE inbound_megolm_sessions ADD ed25519Key TEXT")); + execute(QStringLiteral("PRAGMA user_version = 2;")); + commit(); +} + QByteArray Database::accountPickle() { auto query = prepareQuery(QStringLiteral("SELECT pickle FROM accounts;")); diff --git a/lib/database.h b/lib/database.h index f6a491fb..f9a8df1a 100644 --- a/lib/database.h +++ b/lib/database.h @@ -37,6 +37,7 @@ public: private: void migrateTo1(); + void migrateTo2(); QString m_matrixId; }; } -- cgit v1.2.3 From 01f7641292eb5dff236f434d7140259c429521ca Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Tue, 8 Mar 2022 22:35:56 +0100 Subject: Store time of last decrypted message for each olm session Is required to correctly choose a session to use for sending messages --- lib/connection.cpp | 4 +++- lib/database.cpp | 16 ++++++++++++++-- lib/database.h | 3 ++- 3 files changed, 19 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 11c81edf..506a2bc0 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -216,7 +216,7 @@ public: qCWarning(E2EE) << "Failed to pickle olm session. Error" << std::get(pickleResult); return; } - q->database()->saveOlmSession(senderKey, session->sessionId(), std::get(pickleResult)); + q->database()->saveOlmSession(senderKey, session->sessionId(), std::get(pickleResult), QDateTime::currentDateTime()); } QString sessionDecryptPrekey(const QOlmMessage& message, const QString &senderKey, std::unique_ptr& olmAccount) { @@ -227,6 +227,7 @@ public: qCDebug(E2EE) << "Found inbound session"; const auto result = session->decrypt(message); if(std::holds_alternative(result)) { + q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime()); return std::get(result); } else { qCDebug(E2EE) << "Failed to decrypt prekey message"; @@ -261,6 +262,7 @@ public: for(auto& session : olmSessions[senderKey]) { const auto result = session->decrypt(message); if(std::holds_alternative(result)) { + q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime()); return std::get(result); } } diff --git a/lib/database.cpp b/lib/database.cpp index d070e1de..21e79d58 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -100,6 +100,7 @@ void Database::migrateTo2() qCDebug(DATABASE) << "Migrating database to version 2"; transaction(); execute(QStringLiteral("ALTER TABLE inbound_megolm_sessions ADD ed25519Key TEXT")); + execute(QStringLiteral("ALTER TABLE olm_sessions ADD lastReceived TEXT")); execute(QStringLiteral("PRAGMA user_version = 2;")); commit(); } @@ -141,12 +142,13 @@ void Database::clear() } -void Database::saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle) +void Database::saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle, const QDateTime& timestamp) { - auto query = prepareQuery(QStringLiteral("INSERT INTO olm_sessions(senderKey, sessionId, pickle) VALUES(:senderKey, :sessionId, :pickle);")); + auto query = prepareQuery(QStringLiteral("INSERT INTO olm_sessions(senderKey, sessionId, pickle, lastReceived) VALUES(:senderKey, :sessionId, :pickle, :lastReceived);")); query.bindValue(":senderKey", senderKey); query.bindValue(":sessionId", sessionId); query.bindValue(":pickle", pickle); + query.bindValue(":lastReceived", timestamp); transaction(); execute(query); commit(); @@ -253,3 +255,13 @@ void Database::clearRoomData(const QString& roomId) execute(query3); commit(); } + +void Database::setOlmSessionLastReceived(const QString& sessionId, const QDateTime& timestamp) +{ + auto query = prepareQuery(QStringLiteral("UPDATE olm_sessions SET lastReceived=:lastReceived WHERE sessionId=:sessionId;")); + query.bindValue(":lastReceived", timestamp); + query.bindValue(":sessionId", sessionId); + transaction(); + execute(query); + commit(); +} diff --git a/lib/database.h b/lib/database.h index f9a8df1a..cf241dbc 100644 --- a/lib/database.h +++ b/lib/database.h @@ -27,13 +27,14 @@ public: QByteArray accountPickle(); void setAccountPickle(const QByteArray &pickle); void clear(); - void saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle); + void saveOlmSession(const QString& senderKey, const QString& sessionId, const QByteArray &pickle, const QDateTime& timestamp); UnorderedMap> loadOlmSessions(const PicklingMode& picklingMode); UnorderedMap, QOlmInboundGroupSessionPtr> loadMegolmSessions(const QString& roomId, const PicklingMode& picklingMode); void saveMegolmSession(const QString& roomId, const QString& senderKey, const QString& sessionKey, const QString& ed25519Key, const QByteArray& pickle); void addGroupSessionIndexRecord(const QString& roomId, const QString& sessionId, uint32_t index, const QString& eventId, qint64 ts); std::pair groupSessionIndexRecord(const QString& roomId, const QString& sessionId, qint64 index); void clearRoomData(const QString& roomId); + void setOlmSessionLastReceived(const QString& sessionId, const QDateTime& timestamp); private: void migrateTo1(); -- cgit v1.2.3 From cbc42d892f7fcc0ef269229c5750266c544729b2 Mon Sep 17 00:00:00 2001 From: Tobias Fella <9750016+TobiasFella@users.noreply.github.com> Date: Wed, 9 Mar 2022 20:08:38 +0100 Subject: Update lib/database.cpp Co-authored-by: Carl Schwan --- lib/database.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib') diff --git a/lib/database.cpp b/lib/database.cpp index 21e79d58..70dc1b9b 100644 --- a/lib/database.cpp +++ b/lib/database.cpp @@ -101,6 +101,12 @@ void Database::migrateTo2() transaction(); execute(QStringLiteral("ALTER TABLE inbound_megolm_sessions ADD ed25519Key TEXT")); execute(QStringLiteral("ALTER TABLE olm_sessions ADD lastReceived TEXT")); + + // Add indexes for improving queries speed on larger database + execute(QStringLiteral("CREATE INDEX sessions_session_idx ON olm_sessions(sessionId)")); + execute(QStringLiteral("CREATE INDEX outbound_room_idx ON outbound_megolm_sessions(roomId)")); + execute(QStringLiteral("CREATE INDEX inbound_room_idx ON inbound_megolm_sessions(roomId)")); + execute(QStringLiteral("CREATE INDEX group_session_idx ON group_session_record_index(roomId, sessionId, i)")); execute(QStringLiteral("PRAGMA user_version = 2;")); commit(); } -- cgit v1.2.3 From b8c22ff0663350a019ae918771fac4b6447d2b09 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Wed, 9 Mar 2022 20:23:23 +0100 Subject: Check for empty ed25519 key. --- lib/connection.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/connection.cpp b/lib/connection.cpp index 506a2bc0..cb04ffe8 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -322,6 +322,11 @@ public: << "in Olm plaintext"; return {}; } + //TODO make this do the check mentioned in the E2EE Implementation guide instead + if (decryptedEvent->fullJson()["keys"]["ed25519"].toString().isEmpty()) { + qCDebug(E2EE) << "Event does not contain an ed25519 key"; + return {}; + } // TODO: keys to constants const auto decryptedEventObject = decryptedEvent->fullJson(); -- cgit v1.2.3