From 3f0aa13cb6f83c8768dc30b1a1872b9696992fa7 Mon Sep 17 00:00:00 2001
From: Nicolas Werner <nicolas.werner@hotmail.de>
Date: Sat, 17 Jul 2021 02:14:44 +0200
Subject: [PATCH] Share historical keys

We share all keys with our devices and ones created by us to other
users.
---
 src/Cache.cpp | 24 ++++++++++++++++++++++++
 src/Cache.h   |  2 ++
 src/Cache_p.h |  1 +
 src/Olm.cpp   | 50 ++++++++++++++++++++++++++++----------------------
 4 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/src/Cache.cpp b/src/Cache.cpp
index 1c1561042..7b6a6135a 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -582,6 +582,25 @@ Cache::getOutboundMegolmSession(const std::string &room_id)
         }
 }
 
+std::optional<GroupSessionData>
+Cache::getMegolmSessionData(const MegolmSessionIndex &index)
+{
+        try {
+                using namespace mtx::crypto;
+
+                auto txn = ro_txn(env_);
+
+                std::string_view value;
+                if (megolmSessionDataDb_.get(txn, json(index).dump(), value)) {
+                        return nlohmann::json::parse(value).get<GroupSessionData>();
+                }
+
+                return std::nullopt;
+        } catch (std::exception &e) {
+                nhlog::db()->error("Failed to retrieve Megolm Session Data: {}", e.what());
+                return std::nullopt;
+        }
+}
 //
 // OLM sessions.
 //
@@ -4622,6 +4641,11 @@ inboundMegolmSessionExists(const MegolmSessionIndex &index)
 {
         return instance_->inboundMegolmSessionExists(index);
 }
+std::optional<GroupSessionData>
+getMegolmSessionData(const MegolmSessionIndex &index)
+{
+        return instance_->getMegolmSessionData(index);
+}
 
 //
 // Olm Sessions
diff --git a/src/Cache.h b/src/Cache.h
index 2b5478764..57a36d73a 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -229,6 +229,8 @@ mtx::crypto::InboundGroupSessionPtr
 getInboundMegolmSession(const MegolmSessionIndex &index);
 bool
 inboundMegolmSessionExists(const MegolmSessionIndex &index);
+std::optional<GroupSessionData>
+getMegolmSessionData(const MegolmSessionIndex &index);
 
 //
 // Olm Sessions
diff --git a/src/Cache_p.h b/src/Cache_p.h
index 6f2089254..d1f6307d8 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -259,6 +259,7 @@ public:
         mtx::crypto::InboundGroupSessionPtr getInboundMegolmSession(
           const MegolmSessionIndex &index);
         bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
+        std::optional<GroupSessionData> getMegolmSessionData(const MegolmSessionIndex &index);
 
         //
         // Olm Sessions
diff --git a/src/Olm.cpp b/src/Olm.cpp
index d9447031f..18e2ddcf0 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -631,8 +631,9 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
 
                 // Saving the new megolm session.
                 GroupSessionData session_data{};
-                session_data.message_index = 0;
-                session_data.timestamp     = QDateTime::currentMSecsSinceEpoch();
+                session_data.message_index              = 0;
+                session_data.timestamp                  = QDateTime::currentMSecsSinceEpoch();
+                session_data.sender_claimed_ed25519_key = olm::client()->identity_keys().ed25519;
 
                 sendSessionTo.clear();
 
@@ -886,30 +887,33 @@ handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyR
                 return;
         }
 
-        // Check if we were the sender of the session being requested.
-        if (req.content.sender_key != olm::client()->identity_keys().curve25519) {
-                nhlog::crypto()->debug("ignoring key request {} because we were not the sender: "
-                                       "\nrequested({}) ours({})",
-                                       req.content.request_id,
-                                       req.content.sender_key,
-                                       olm::client()->identity_keys().curve25519);
+        // Check if we were the sender of the session being requested (unless it is actually us
+        // requesting the session).
+        if (req.sender != http::client()->user_id().to_string() &&
+            req.content.sender_key != olm::client()->identity_keys().curve25519) {
+                nhlog::crypto()->debug(
+                  "ignoring key request {} because we did not create the requested session: "
+                  "\nrequested({}) ours({})",
+                  req.content.request_id,
+                  req.content.sender_key,
+                  olm::client()->identity_keys().curve25519);
                 return;
         }
 
+        // Check that the requested session_id and the one we have saved match.
+        MegolmSessionIndex index{};
+        index.room_id    = req.content.room_id;
+        index.session_id = req.content.session_id;
+        index.sender_key = req.content.sender_key;
+
         // Check if we have the keys for the requested session.
-        auto outboundSession = cache::getOutboundMegolmSession(req.content.room_id);
-        if (!outboundSession.session) {
+        auto sessionData = cache::getMegolmSessionData(index);
+        if (!sessionData) {
                 nhlog::crypto()->warn("requested session not found in room: {}",
                                       req.content.room_id);
                 return;
         }
 
-        // Check that the requested session_id and the one we have saved match.
-        MegolmSessionIndex index{};
-        index.room_id    = req.content.room_id;
-        index.session_id = req.content.session_id;
-        index.sender_key = olm::client()->identity_keys().curve25519;
-
         const auto session = cache::getInboundMegolmSession(index);
         if (!session) {
                 nhlog::crypto()->warn("No session with id {} in db", req.content.session_id);
@@ -942,11 +946,11 @@ handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyR
 
         bool shouldSeeKeys    = false;
         uint64_t minimumIndex = -1;
-        if (outboundSession.data.currently.keys.count(req.sender)) {
-                if (outboundSession.data.currently.keys.at(req.sender)
+        if (sessionData->currently.keys.count(req.sender)) {
+                if (sessionData->currently.keys.at(req.sender)
                       .deviceids.count(req.content.requesting_device_id)) {
                         shouldSeeKeys = true;
-                        minimumIndex  = outboundSession.data.currently.keys.at(req.sender)
+                        minimumIndex  = sessionData->currently.keys.at(req.sender)
                                          .deviceids.at(req.content.requesting_device_id);
                 }
         }
@@ -976,8 +980,9 @@ handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyR
                 forward_key.sender_key  = index.sender_key;
 
                 // TODO(Nico): Figure out if this is correct
-                forward_key.sender_claimed_ed25519_key = olm::client()->identity_keys().ed25519;
-                forward_key.forwarding_curve25519_key_chain = {};
+                forward_key.sender_claimed_ed25519_key = sessionData->sender_claimed_ed25519_key;
+                forward_key.forwarding_curve25519_key_chain =
+                  sessionData->forwarding_curve25519_key_chain;
 
                 send_megolm_key_to_device(
                   req.sender, req.content.requesting_device_id, forward_key);
@@ -998,6 +1003,7 @@ send_megolm_key_to_device(const std::string &user_id,
         std::map<std::string, std::vector<std::string>> targets;
         targets[user_id] = {device_id};
         send_encrypted_to_device_messages(targets, room_key);
+        nhlog::crypto()->debug("Forwarded key to {}:{}", user_id, device_id);
 }
 
 DecryptionResult
-- 
GitLab