summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--io.github.NhekoReborn.Nheko.yaml2
-rw-r--r--src/ChatPage.cpp51
-rw-r--r--src/ChatPage.h5
4 files changed, 50 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 57bb74b6..0395a14c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -400,7 +400,7 @@ if(USE_BUNDLED_MTXCLIENT)
 	FetchContent_Declare(
 		MatrixClient
 		GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
-		GIT_TAG        288f585725ecdf2e5e04c5985fdbf658a7fe8a1b
+		GIT_TAG        2122209f04681ac8d61ddd0fa4fcbc8368eb5b5b
 		)
 	set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
 	set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
@@ -418,7 +418,7 @@ if(USE_BUNDLED_OLM)
 	set(OLM_TESTS OFF CACHE INTERNAL "")
 	FetchContent_MakeAvailable(Olm)
 else()
-	find_package(Olm 3 REQUIRED)
+	find_package(Olm 3.2.7 REQUIRED)
 	set_package_properties(Olm PROPERTIES
 		DESCRIPTION "An implementation of the Double Ratchet cryptographic ratchet"
 		URL "https://git.matrix.org/git/olm/about/"
diff --git a/io.github.NhekoReborn.Nheko.yaml b/io.github.NhekoReborn.Nheko.yaml
index 5772fde3..241900a7 100644
--- a/io.github.NhekoReborn.Nheko.yaml
+++ b/io.github.NhekoReborn.Nheko.yaml
@@ -203,7 +203,7 @@ modules:
     buildsystem: cmake-ninja
     name: mtxclient
     sources:
-      - commit: 288f585725ecdf2e5e04c5985fdbf658a7fe8a1b
+      - commit: 2122209f04681ac8d61ddd0fa4fcbc8368eb5b5b
         #tag: v0.7.0
         type: git
         url: https://github.com/Nheko-Reborn/mtxclient.git
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 35489f66..37605ab9 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -236,6 +236,15 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QObject *parent)
 
     connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage);
 
+    connect(
+      this,
+      &ChatPage::startRemoveFallbackKeyTimer,
+      this,
+      [this]() {
+          QTimer::singleShot(std::chrono::minutes(5), this, &ChatPage::removeOldFallbackKey);
+      },
+      Qt::QueuedConnection);
+
     connectCallMessage<mtx::events::msg::CallInvite>();
     connectCallMessage<mtx::events::msg::CallCandidates>();
     connectCallMessage<mtx::events::msg::CallAnswer>();
@@ -432,6 +441,7 @@ ChatPage::loadStateFromCache()
     emit contentLoaded();
 
     // Start receiving events.
+    connect(this, &ChatPage::newSyncResponse, &ChatPage::startRemoveFallbackKeyTimer);
     emit trySyncCb();
 }
 
@@ -495,7 +505,7 @@ ChatPage::tryInitialSync()
 
     // Upload one time keys for the device.
     nhlog::crypto()->info("generating one time keys");
-    olm::client()->generate_one_time_keys(MAX_ONETIME_KEYS);
+    olm::client()->generate_one_time_keys(MAX_ONETIME_KEYS, true);
 
     http::client()->upload_keys(
       olm::client()->create_upload_keys_request(),
@@ -519,6 +529,7 @@ ChatPage::tryInitialSync()
               return;
           }
 
+          olm::client()->forget_old_fallback_key();
           olm::mark_keys_as_published();
 
           for (const auto &entry : res.one_time_key_counts)
@@ -608,7 +619,7 @@ ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string
     nhlog::net()->debug("sync completed: {}", res.next_batch);
 
     // Ensure that we have enough one-time keys available.
-    ensureOneTimeKeyCount(res.device_one_time_keys_count);
+    ensureOneTimeKeyCount(res.device_one_time_keys_count, res.device_unused_fallback_key_types);
 
     // TODO: fine grained error handling
     try {
@@ -989,26 +1000,38 @@ ChatPage::verifyOneTimeKeyCountAfterStartup()
           nhlog::crypto()->info(
             "Fetched server key count {} {}", count, mtx::crypto::SIGNED_CURVE25519);
 
-          ensureOneTimeKeyCount(key_counts);
+          ensureOneTimeKeyCount(key_counts, std::nullopt);
       });
 }
 
 void
-ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts)
+ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts,
+                                const std::optional<std::vector<std::string>> &unused_fallback_keys)
 {
     if (auto count = counts.find(mtx::crypto::SIGNED_CURVE25519); count != counts.end()) {
+        bool replace_fallback_key = false;
+        if (unused_fallback_keys &&
+            std::find(unused_fallback_keys->begin(),
+                      unused_fallback_keys->end(),
+                      mtx::crypto::SIGNED_CURVE25519) == unused_fallback_keys->end())
+            replace_fallback_key = true;
         nhlog::crypto()->debug(
-          "Updated server key count {} {}", count->second, mtx::crypto::SIGNED_CURVE25519);
+          "Updated server key count {} {}, fallback keys supported: {}, new fallback key: {}",
+          count->second,
+          mtx::crypto::SIGNED_CURVE25519,
+          unused_fallback_keys.has_value(),
+          replace_fallback_key);
 
-        if (count->second < MAX_ONETIME_KEYS) {
+        if (count->second < MAX_ONETIME_KEYS || replace_fallback_key) {
             const size_t nkeys = MAX_ONETIME_KEYS - count->second;
 
             nhlog::crypto()->info("uploading {} {} keys", nkeys, mtx::crypto::SIGNED_CURVE25519);
-            olm::client()->generate_one_time_keys(nkeys);
+            olm::client()->generate_one_time_keys(nkeys, replace_fallback_key);
 
             http::client()->upload_keys(
               olm::client()->create_upload_keys_request(),
-              [](const mtx::responses::UploadKeys &, mtx::http::RequestErr err) {
+              [replace_fallback_key, this](const mtx::responses::UploadKeys &,
+                                           mtx::http::RequestErr err) {
                   if (err) {
                       nhlog::crypto()->warn("failed to update one-time keys: {}", err);
 
@@ -1018,6 +1041,10 @@ ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts)
 
                   // mark as published anyway, otherwise we may end up in a loop.
                   olm::mark_keys_as_published();
+
+                  if (replace_fallback_key) {
+                      emit startRemoveFallbackKeyTimer();
+                  }
               });
         } else if (count->second > 2 * MAX_ONETIME_KEYS) {
             nhlog::crypto()->warn("too many one-time keys, deleting 1");
@@ -1036,6 +1063,14 @@ ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts)
 }
 
 void
+ChatPage::removeOldFallbackKey()
+{
+    olm::client()->forget_old_fallback_key();
+    olm::mark_keys_as_published();
+    disconnect(this, &ChatPage::newSyncResponse, this, &ChatPage::removeOldFallbackKey);
+}
+
+void
 ChatPage::getProfileInfo()
 {
     const auto userid = utils::localUser().toStdString();
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 165f7068..5228aa8e 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -127,6 +127,7 @@ signals:
     void leftRoom(const QString &room_id);
     void newRoom(const QString &room_id);
     void changeToRoom(const QString &room_id);
+    void startRemoveFallbackKeyTimer();
 
     void initializeViews(const mtx::responses::Sync &rooms);
     void initializeEmptyViews();
@@ -183,7 +184,9 @@ private:
     void tryInitialSync();
     void trySync();
     void verifyOneTimeKeyCountAfterStartup();
-    void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts);
+    void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts,
+                               const std::optional<std::vector<std::string>> &fallback_keys);
+    void removeOldFallbackKey();
     void getProfileInfo();
     void getBackupVersion();