aboutsummaryrefslogtreecommitdiff
path: root/lib/connection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/connection.cpp')
-rw-r--r--lib/connection.cpp70
1 files changed, 66 insertions, 4 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp
index d99ab64d..28377dd9 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -33,6 +33,7 @@
#include "jobs/downloadfilejob.h"
#include "jobs/mediathumbnailjob.h"
#include "jobs/syncjob.h"
+#include <variant>
#ifdef Quotient_E2EE_ENABLED
# include "e2ee/qolmaccount.h"
@@ -223,13 +224,23 @@ public:
std::pair<QString, QString> sessionDecryptPrekey(const QOlmMessage& message, const QString &senderKey, std::unique_ptr<QOlmAccount>& olmAccount)
{
Q_ASSERT(message.type() == QOlmMessage::PreKey);
- for(auto& session : olmSessions[senderKey]) {
+ for (size_t i = 0; i < olmSessions[senderKey].size(); i++) {
+ auto& session = olmSessions[senderKey][i];
const auto matches = session->matchesInboundSessionFrom(senderKey, message);
if(std::holds_alternative<bool>(matches) && std::get<bool>(matches)) {
qCDebug(E2EE) << "Found inbound session";
const auto result = session->decrypt(message);
if(std::holds_alternative<QString>(result)) {
q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime());
+ auto pickle = session->pickle(q->picklingMode());
+ if (std::holds_alternative<QByteArray>(pickle)) {
+ q->database()->updateOlmSession(senderKey, session->sessionId(), std::get<QByteArray>(pickle));
+ } else {
+ qCWarning(E2EE) << "Failed to pickle olm session.";
+ }
+ auto s = std::move(session);
+ olmSessions[senderKey].erase(olmSessions[senderKey].begin() + i);
+ olmSessions[senderKey].insert(olmSessions[senderKey].begin(), std::move(s));
return { std::get<QString>(result), session->sessionId() };
} else {
qCDebug(E2EE) << "Failed to decrypt prekey message";
@@ -251,7 +262,7 @@ public:
const auto result = newSession->decrypt(message);
QString sessionId = newSession->sessionId();
saveSession(newSession, senderKey);
- olmSessions[senderKey].push_back(std::move(newSession));
+ olmSessions[senderKey].insert(olmSessions[senderKey].begin(), std::move(newSession));
if(std::holds_alternative<QString>(result)) {
return { std::get<QString>(result), sessionId };
} else {
@@ -262,10 +273,20 @@ public:
std::pair<QString, QString> sessionDecryptGeneral(const QOlmMessage& message, const QString &senderKey)
{
Q_ASSERT(message.type() == QOlmMessage::General);
- for(auto& session : olmSessions[senderKey]) {
+ for (size_t i = 0; i < olmSessions[senderKey].size(); i++) {
+ auto& session = olmSessions[senderKey][i];
const auto result = session->decrypt(message);
if(std::holds_alternative<QString>(result)) {
q->database()->setOlmSessionLastReceived(QString(session->sessionId()), QDateTime::currentDateTime());
+ auto pickle = session->pickle(q->picklingMode());
+ if (std::holds_alternative<QByteArray>(pickle)) {
+ q->database()->updateOlmSession(senderKey, session->sessionId(), std::get<QByteArray>(pickle));
+ } else {
+ qCWarning(E2EE) << "Failed to pickle olm session.";
+ }
+ auto s = std::move(session);
+ olmSessions[senderKey].erase(olmSessions[senderKey].begin() + i);
+ olmSessions[senderKey].insert(olmSessions[senderKey].begin(), std::move(s));
return { std::get<QString>(result), session->sessionId() };
}
}
@@ -1338,7 +1359,7 @@ Connection::sendToDevices(const QString& eventType,
[&jsonUser](const auto& deviceToEvents) {
jsonUser.insert(
deviceToEvents.first,
- deviceToEvents.second.contentJson());
+ deviceToEvents.second->contentJson());
});
});
return callApi<SendToDeviceJob>(BackgroundRequest, eventType,
@@ -2225,6 +2246,47 @@ QString Connection::edKeyForUserDevice(const QString& user, const QString& devic
return d->deviceKeys[user][device].keys["ed25519:" % device];
}
+bool Connection::hasOlmSession(User* user, const QString& deviceId) const
+{
+ const auto& curveKey = curveKeyForUserDevice(user->id(), deviceId);
+ return d->olmSessions.contains(curveKey) && d->olmSessions[curveKey].size() > 0;
+}
+
+QPair<QOlmMessage::Type, QByteArray> Connection::olmEncryptMessage(User* user, const QString& device, const QByteArray& message)
+{
+ const auto& curveKey = curveKeyForUserDevice(user->id(), device);
+ QOlmMessage::Type type = d->olmSessions[curveKey][0]->encryptMessageType();
+ auto result = d->olmSessions[curveKey][0]->encrypt(message);
+ auto pickle = d->olmSessions[curveKey][0]->pickle(picklingMode());
+ if (std::holds_alternative<QByteArray>(pickle)) {
+ database()->updateOlmSession(curveKey, d->olmSessions[curveKey][0]->sessionId(), std::get<QByteArray>(pickle));
+ } else {
+ qCWarning(E2EE) << "Failed to pickle olm session.";
+ }
+ return qMakePair(type, result.toCiphertext());
+}
+
+void Connection::createOlmSession(const QString& theirIdentityKey, const QString& theirOneTimeKey)
+{
+ auto session = QOlmSession::createOutboundSession(olmAccount(), theirIdentityKey, theirOneTimeKey);
+ if (std::holds_alternative<QOlmError>(session)) {
+ qCWarning(E2EE) << "Failed to create olm session for " << theirIdentityKey << std::get<QOlmError>(session);
+ return;
+ }
+ d->saveSession(std::get<std::unique_ptr<QOlmSession>>(session), theirIdentityKey);
+ d->olmSessions[theirIdentityKey].push_back(std::move(std::get<std::unique_ptr<QOlmSession>>(session)));
+}
+
+QOlmOutboundGroupSessionPtr Connection::loadCurrentOutboundMegolmSession(Room* room)
+{
+ return d->database->loadCurrentOutboundMegolmSession(room->id(), d->picklingMode);
+}
+
+void Connection::saveCurrentOutboundMegolmSession(Room *room, const QOlmOutboundGroupSessionPtr& data)
+{
+ d->database->saveCurrentOutboundMegolmSession(room->id(), d->picklingMode, data);
+}
+
bool Connection::isKnownCurveKey(const QString& user, const QString& curveKey)
{
auto query = database()->prepareQuery(QStringLiteral("SELECT * FROM tracked_devices WHERE matrixId=:matrixId AND curveKey=:curveKey"));