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, 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(); connectCallMessage(); connectCallMessage(); @@ -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 &counts) +ChatPage::ensureOneTimeKeyCount(const std::map &counts, + const std::optional> &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 &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"); @@ -1035,6 +1062,14 @@ ChatPage::ensureOneTimeKeyCount(const std::map &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() { 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 &counts); + void ensureOneTimeKeyCount(const std::map &counts, + const std::optional> &fallback_keys); + void removeOldFallbackKey(); void getProfileInfo(); void getBackupVersion();