Add support for fallback keys

This commit is contained in:
Nicolas Werner 2022-05-14 01:42:21 +02:00
parent 7f2ae13c43
commit 0a65019242
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
4 changed files with 50 additions and 12 deletions

View File

@ -400,7 +400,7 @@ if(USE_BUNDLED_MTXCLIENT)
FetchContent_Declare( FetchContent_Declare(
MatrixClient MatrixClient
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git 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_EXAMPLES OFF CACHE INTERNAL "")
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "") set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
@ -418,7 +418,7 @@ if(USE_BUNDLED_OLM)
set(OLM_TESTS OFF CACHE INTERNAL "") set(OLM_TESTS OFF CACHE INTERNAL "")
FetchContent_MakeAvailable(Olm) FetchContent_MakeAvailable(Olm)
else() else()
find_package(Olm 3 REQUIRED) find_package(Olm 3.2.7 REQUIRED)
set_package_properties(Olm PROPERTIES set_package_properties(Olm PROPERTIES
DESCRIPTION "An implementation of the Double Ratchet cryptographic ratchet" DESCRIPTION "An implementation of the Double Ratchet cryptographic ratchet"
URL "https://git.matrix.org/git/olm/about/" URL "https://git.matrix.org/git/olm/about/"

View File

@ -203,7 +203,7 @@ modules:
buildsystem: cmake-ninja buildsystem: cmake-ninja
name: mtxclient name: mtxclient
sources: sources:
- commit: 288f585725ecdf2e5e04c5985fdbf658a7fe8a1b - commit: 2122209f04681ac8d61ddd0fa4fcbc8368eb5b5b
#tag: v0.7.0 #tag: v0.7.0
type: git type: git
url: https://github.com/Nheko-Reborn/mtxclient.git url: https://github.com/Nheko-Reborn/mtxclient.git

View File

@ -236,6 +236,15 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QObject *parent)
connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage); 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::CallInvite>();
connectCallMessage<mtx::events::msg::CallCandidates>(); connectCallMessage<mtx::events::msg::CallCandidates>();
connectCallMessage<mtx::events::msg::CallAnswer>(); connectCallMessage<mtx::events::msg::CallAnswer>();
@ -432,6 +441,7 @@ ChatPage::loadStateFromCache()
emit contentLoaded(); emit contentLoaded();
// Start receiving events. // Start receiving events.
connect(this, &ChatPage::newSyncResponse, &ChatPage::startRemoveFallbackKeyTimer);
emit trySyncCb(); emit trySyncCb();
} }
@ -495,7 +505,7 @@ ChatPage::tryInitialSync()
// Upload one time keys for the device. // Upload one time keys for the device.
nhlog::crypto()->info("generating one time keys"); 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( http::client()->upload_keys(
olm::client()->create_upload_keys_request(), olm::client()->create_upload_keys_request(),
@ -519,6 +529,7 @@ ChatPage::tryInitialSync()
return; return;
} }
olm::client()->forget_old_fallback_key();
olm::mark_keys_as_published(); olm::mark_keys_as_published();
for (const auto &entry : res.one_time_key_counts) 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); nhlog::net()->debug("sync completed: {}", res.next_batch);
// Ensure that we have enough one-time keys available. // 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 // TODO: fine grained error handling
try { try {
@ -989,26 +1000,38 @@ ChatPage::verifyOneTimeKeyCountAfterStartup()
nhlog::crypto()->info( nhlog::crypto()->info(
"Fetched server key count {} {}", count, mtx::crypto::SIGNED_CURVE25519); "Fetched server key count {} {}", count, mtx::crypto::SIGNED_CURVE25519);
ensureOneTimeKeyCount(key_counts); ensureOneTimeKeyCount(key_counts, std::nullopt);
}); });
} }
void 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()) { 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( 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; const size_t nkeys = MAX_ONETIME_KEYS - count->second;
nhlog::crypto()->info("uploading {} {} keys", nkeys, mtx::crypto::SIGNED_CURVE25519); 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( http::client()->upload_keys(
olm::client()->create_upload_keys_request(), 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) { if (err) {
nhlog::crypto()->warn("failed to update one-time keys: {}", 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. // mark as published anyway, otherwise we may end up in a loop.
olm::mark_keys_as_published(); olm::mark_keys_as_published();
if (replace_fallback_key) {
emit startRemoveFallbackKeyTimer();
}
}); });
} else if (count->second > 2 * MAX_ONETIME_KEYS) { } else if (count->second > 2 * MAX_ONETIME_KEYS) {
nhlog::crypto()->warn("too many one-time keys, deleting 1"); nhlog::crypto()->warn("too many one-time keys, deleting 1");
@ -1035,6 +1062,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 void
ChatPage::getProfileInfo() ChatPage::getProfileInfo()
{ {

View File

@ -127,6 +127,7 @@ signals:
void leftRoom(const QString &room_id); void leftRoom(const QString &room_id);
void newRoom(const QString &room_id); void newRoom(const QString &room_id);
void changeToRoom(const QString &room_id); void changeToRoom(const QString &room_id);
void startRemoveFallbackKeyTimer();
void initializeViews(const mtx::responses::Sync &rooms); void initializeViews(const mtx::responses::Sync &rooms);
void initializeEmptyViews(); void initializeEmptyViews();
@ -183,7 +184,9 @@ private:
void tryInitialSync(); void tryInitialSync();
void trySync(); void trySync();
void verifyOneTimeKeyCountAfterStartup(); 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 getProfileInfo();
void getBackupVersion(); void getBackupVersion();