diff --git a/src/Cache.cpp b/src/Cache.cpp
index 8b8b2985..6b28ca91 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -42,6 +42,7 @@ static const std::string SECRET("secret");
static const std::string_view NEXT_BATCH_KEY("next_batch");
static const std::string_view OLM_ACCOUNT_KEY("olm_account");
static const std::string_view CACHE_FORMAT_VERSION_KEY("cache_format_version");
+static const std::string_view CURRENT_ONLINE_BACKUP_VERSION("current_online_backup_version");
constexpr size_t MAX_RESTORED_MESSAGES = 30'000;
@@ -724,6 +725,36 @@ Cache::restoreOlmAccount()
}
void
+Cache::saveBackupVersion(const OnlineBackupVersion &data)
+{
+ auto txn = lmdb::txn::begin(env_);
+ syncStateDb_.put(txn, CURRENT_ONLINE_BACKUP_VERSION, nlohmann::json(data).dump());
+ txn.commit();
+}
+
+void
+Cache::deleteBackupVersion()
+{
+ auto txn = lmdb::txn::begin(env_);
+ syncStateDb_.del(txn, CURRENT_ONLINE_BACKUP_VERSION);
+ txn.commit();
+}
+
+std::optional<OnlineBackupVersion>
+Cache::backupVersion()
+{
+ try {
+ auto txn = ro_txn(env_);
+ std::string_view v;
+ syncStateDb_.get(txn, CURRENT_ONLINE_BACKUP_VERSION, v);
+
+ return nlohmann::json::parse(v).get<OnlineBackupVersion>();
+ } catch (...) {
+ return std::nullopt;
+ }
+}
+
+void
Cache::storeSecret(const std::string name, const std::string secret)
{
auto settings = UserSettings::instance();
@@ -4114,6 +4145,20 @@ from_json(const json &j, VerificationCache &info)
info.device_blocked = j.at("device_blocked").get<std::set<std::string>>();
}
+void
+to_json(json &j, const OnlineBackupVersion &info)
+{
+ j["v"] = info.version;
+ j["a"] = info.algorithm;
+}
+
+void
+from_json(const json &j, OnlineBackupVersion &info)
+{
+ info.version = j.at("v").get<std::string>();
+ info.algorithm = j.at("a").get<std::string>();
+}
+
std::optional<VerificationCache>
Cache::verificationCache(const std::string &user_id, lmdb::txn &txn)
{
@@ -4461,6 +4506,7 @@ to_json(nlohmann::json &obj, const GroupSessionData &msg)
{
obj["message_index"] = msg.message_index;
obj["ts"] = msg.timestamp;
+ obj["trust"] = msg.trusted;
obj["sender_claimed_ed25519_key"] = msg.sender_claimed_ed25519_key;
obj["forwarding_curve25519_key_chain"] = msg.forwarding_curve25519_key_chain;
@@ -4475,6 +4521,7 @@ from_json(const nlohmann::json &obj, GroupSessionData &msg)
{
msg.message_index = obj.at("message_index");
msg.timestamp = obj.value("ts", 0ULL);
+ msg.trusted = obj.value("trust", true);
msg.sender_claimed_ed25519_key = obj.value("sender_claimed_ed25519_key", "");
msg.forwarding_curve25519_key_chain =
diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h
index 6c402674..80dd1046 100644
--- a/src/CacheCryptoStructs.h
+++ b/src/CacheCryptoStructs.h
@@ -47,6 +47,11 @@ struct GroupSessionData
uint64_t message_index = 0;
uint64_t timestamp = 0;
+ // If we got the session via key sharing or forwarding, we can usually trust it.
+ // If it came from asymmetric key backup, it is not trusted.
+ // TODO(Nico): What about forwards? They might come from key backup?
+ bool trusted = true;
+
std::string sender_claimed_ed25519_key;
std::vector<std::string> forwarding_curve25519_key_chain;
@@ -83,6 +88,13 @@ from_json(const nlohmann::json &obj, DevicePublicKeys &msg);
//! Represents a unique megolm session identifier.
struct MegolmSessionIndex
{
+ MegolmSessionIndex() = default;
+ MegolmSessionIndex(std::string room_id_, const mtx::events::msg::Encrypted &e)
+ : room_id(std::move(room_id_))
+ , session_id(e.session_id)
+ , sender_key(e.sender_key)
+ {}
+
//! The room in which this session exists.
std::string room_id;
//! The session_id of the megolm session.
@@ -167,3 +179,16 @@ void
to_json(nlohmann::json &j, const VerificationCache &info);
void
from_json(const nlohmann::json &j, VerificationCache &info);
+
+struct OnlineBackupVersion
+{
+ //! the version of the online backup currently enabled
+ std::string version;
+ //! the algorithm used by the backup
+ std::string algorithm;
+};
+
+void
+to_json(nlohmann::json &j, const OnlineBackupVersion &info);
+void
+from_json(const nlohmann::json &j, OnlineBackupVersion &info);
diff --git a/src/Cache_p.h b/src/Cache_p.h
index 748404d1..8322a6af 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -287,6 +287,10 @@ public:
void saveOlmAccount(const std::string &pickled);
std::string restoreOlmAccount();
+ void saveBackupVersion(const OnlineBackupVersion &data);
+ void deleteBackupVersion();
+ std::optional<OnlineBackupVersion> backupVersion();
+
void storeSecret(const std::string name, const std::string secret);
void deleteSecret(const std::string name);
std::optional<std::string> secret(const std::string name);
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 8a0e891b..639f3818 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -385,6 +385,7 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token)
}
getProfileInfo();
+ getBackupVersion();
tryInitialSync();
}
@@ -418,6 +419,7 @@ ChatPage::loadStateFromCache()
nhlog::crypto()->info("curve25519: {}", olm::client()->identity_keys().curve25519);
getProfileInfo();
+ getBackupVersion();
emit contentLoaded();
@@ -975,6 +977,104 @@ ChatPage::getProfileInfo()
}
void
+ChatPage::getBackupVersion()
+{
+ if (!UserSettings::instance()->useOnlineKeyBackup()) {
+ nhlog::crypto()->info("Online key backup disabled.");
+ return;
+ }
+
+ http::client()->backup_version(
+ [this](const mtx::responses::backup::BackupVersion &res, mtx::http::RequestErr err) {
+ if (err) {
+ nhlog::net()->warn("Failed to retrieve backup version");
+ if (err->status_code == 404)
+ cache::client()->deleteBackupVersion();
+ return;
+ }
+
+ // switch to UI thread for secrets stuff
+ QTimer::singleShot(0, this, [this, res] {
+ auto auth_data = nlohmann::json::parse(res.auth_data);
+
+ if (res.algorithm == "m.megolm_backup.v1.curve25519-aes-sha2") {
+ auto key =
+ cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
+ if (!key) {
+ nhlog::crypto()->info("No key for online key backup.");
+ cache::client()->deleteBackupVersion();
+ return;
+ }
+
+ using namespace mtx::crypto;
+ auto pubkey = CURVE25519_public_key_from_private(
+ to_binary_buf(base642bin(*key)));
+
+ if (auth_data["public_key"].get<std::string>() != pubkey) {
+ nhlog::crypto()->info(
+ "Our backup key {} does not match the one "
+ "used in the online backup {}",
+ pubkey,
+ auth_data["public_key"]);
+ cache::client()->deleteBackupVersion();
+ return;
+ }
+
+ nhlog::crypto()->info("Using online key backup.");
+ OnlineBackupVersion data{};
+ data.algorithm = res.algorithm;
+ data.version = res.version;
+ cache::client()->saveBackupVersion(data);
+
+ // We really don't need to add our signature.
+ // if (!auth_data["signatures"]
+ // [http::client()->user_id().to_string()]
+ // .contains("ed25519:" +
+ // http::client()->device_id())) {
+ // // add our signature
+ // // This is not strictly necessary, but some Element
+ // // clients rely on it. We assume the master_key
+ // signature
+ // // already exists and add our device signature just to
+ // be
+ // // safe, even though just the master signature is
+ // enough,
+ // // if cross-signing is used.
+ // auto signatures = auth_data["signatures"];
+ // auth_data.erase("signatures");
+ // auth_data.erase("unsigned");
+ // signatures[http::client()->user_id().to_string()]
+ // ["ed25519:" + http::client()->device_id()] =
+ // olm::client()->sign_message(auth_data.dump());
+ // auth_data["signatures"] = signatures;
+
+ // auto copy = res;
+ // copy.auth_data = auth_data.dump();
+ // http::client()->update_backup_version(
+ // res.version, copy, [](mtx::http::RequestErr e) {
+ // if (e) {
+ // nhlog::crypto()->error(
+ // "Failed to update online backup "
+ // "signatures: {} - {}",
+ // mtx::errors::to_string(
+ // e->matrix_error.errcode),
+ // e->matrix_error.error);
+ // } else {
+ // nhlog::crypto()->info(
+ // "Updated key backup signatures");
+ // }
+ // });
+ //}
+ } else {
+ nhlog::crypto()->info("Unsupported key backup algorithm: {}",
+ res.algorithm);
+ cache::client()->deleteBackupVersion();
+ }
+ });
+ });
+}
+
+void
ChatPage::initiateLogout()
{
http::client()->logout([this](const mtx::responses::Logout &, mtx::http::RequestErr err) {
diff --git a/src/ChatPage.h b/src/ChatPage.h
index c90b87f5..dfe94c37 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -182,6 +182,7 @@ private:
void trySync();
void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts);
void getProfileInfo();
+ void getBackupVersion();
//! Check if the given room is currently open.
bool isRoomActive(const QString &room_id);
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 8bc90f29..396e1ab1 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -130,26 +130,29 @@ MainWindow::MainWindow(QWidget *parent)
trayIcon_->setVisible(userSettings_->tray());
- if (hasActiveUser()) {
- QString token = userSettings_->accessToken();
- QString home_server = userSettings_->homeserver();
- QString user_id = userSettings_->userId();
- QString device_id = userSettings_->deviceId();
-
- http::client()->set_access_token(token.toStdString());
- http::client()->set_server(home_server.toStdString());
- http::client()->set_device_id(device_id.toStdString());
-
- try {
- using namespace mtx::identifiers;
- http::client()->set_user(parse<User>(user_id.toStdString()));
- } catch (const std::invalid_argument &) {
- nhlog::ui()->critical("bootstrapped with invalid user_id: {}",
- user_id.toStdString());
- }
+ // load cache on event loop
+ QTimer::singleShot(0, this, [this] {
+ if (hasActiveUser()) {
+ QString token = userSettings_->accessToken();
+ QString home_server = userSettings_->homeserver();
+ QString user_id = userSettings_->userId();
+ QString device_id = userSettings_->deviceId();
+
+ http::client()->set_access_token(token.toStdString());
+ http::client()->set_server(home_server.toStdString());
+ http::client()->set_device_id(device_id.toStdString());
+
+ try {
+ using namespace mtx::identifiers;
+ http::client()->set_user(parse<User>(user_id.toStdString()));
+ } catch (const std::invalid_argument &) {
+ nhlog::ui()->critical("bootstrapped with invalid user_id: {}",
+ user_id.toStdString());
+ }
- showChatPage();
- }
+ showChatPage();
+ }
+ });
if (loadJdenticonPlugin()) {
nhlog::ui()->info("loaded jdenticon.");
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 2c9ac5a3..05eefce4 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -833,6 +833,8 @@ import_inbound_megolm_session(
data.forwarding_curve25519_key_chain =
roomKey.content.forwarding_curve25519_key_chain;
data.sender_claimed_ed25519_key = roomKey.content.sender_claimed_ed25519_key;
+ // may have come from online key backup, so we can't trust it...
+ data.trusted = false;
cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
} catch (const lmdb::error &e) {
@@ -857,6 +859,97 @@ mark_keys_as_published()
}
void
+lookup_keybackup(const std::string room, const std::string session_id)
+{
+ if (!UserSettings::instance()->useOnlineKeyBackup()) {
+ // Online key backup disabled
+ return;
+ }
+
+ auto backupVersion = cache::client()->backupVersion();
+ if (!backupVersion) {
+ // no trusted OKB
+ return;
+ }
+
+ using namespace mtx::crypto;
+
+ auto decryptedSecret = cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
+ if (!decryptedSecret) {
+ // no backup key available
+ return;
+ }
+ auto sessionDecryptionKey = to_binary_buf(base642bin(*decryptedSecret));
+
+ http::client()->room_keys(
+ backupVersion->version,
+ room,
+ session_id,
+ [room, session_id, sessionDecryptionKey](const mtx::responses::backup::SessionBackup &bk,
+ mtx::http::RequestErr err) {
+ if (err) {
+ if (err->status_code != 404)
+ nhlog::crypto()->error(
+ "Failed to dowload key {}:{}: {} - {}",
+ room,
+ session_id,
+ mtx::errors::to_string(err->matrix_error.errcode),
+ err->matrix_error.error);
+ return;
+ }
+ try {
+ auto session = decrypt_session(bk.session_data, sessionDecryptionKey);
+
+ if (session.algorithm != mtx::crypto::MEGOLM_ALGO)
+ // don't know this algorithm
+ return;
+
+ MegolmSessionIndex index;
+ index.room_id = room;
+ index.session_id = session_id;
+ index.sender_key = session.sender_key;
+
+ GroupSessionData data{};
+ data.forwarding_curve25519_key_chain =
+ session.forwarding_curve25519_key_chain;
+ data.sender_claimed_ed25519_key = session.sender_claimed_keys["ed25519"];
+ // online key backup can't be trusted, because anyone can upload to it.
+ data.trusted = false;
+
+ auto megolm_session =
+ olm::client()->import_inbound_group_session(session.session_key);
+
+ if (!cache::inboundMegolmSessionExists(index) ||
+ olm_inbound_group_session_first_known_index(megolm_session.get()) <
+ olm_inbound_group_session_first_known_index(
+ cache::getInboundMegolmSession(index).get())) {
+ cache::saveInboundMegolmSession(
+ index, std::move(megolm_session), data);
+
+ nhlog::crypto()->info("imported inbound megolm session "
+ "from key backup ({}, {})",
+ room,
+ session_id);
+
+ // call on UI thread
+ QTimer::singleShot(0, ChatPage::instance(), [index] {
+ ChatPage::instance()->receivedSessionKey(
+ index.room_id, index.session_id);
+ });
+ }
+ } catch (const lmdb::error &e) {
+ nhlog::crypto()->critical("failed to save inbound megolm session: {}",
+ e.what());
+ return;
+ } catch (const mtx::crypto::olm_exception &e) {
+ nhlog::crypto()->critical("failed to import inbound megolm session: {}",
+ e.what());
+ return;
+ }
+ });
+}
+
+void
send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
const std::string &request_id,
bool cancel)
@@ -898,6 +991,8 @@ send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
e.sender,
e.content.device_id);
});
+
+ // http::client()->room_keys
}
void
@@ -1095,12 +1190,15 @@ decryptEvent(const MegolmSessionIndex &index,
}
crypto::Trust
-calculate_trust(const std::string &user_id, const std::string &curve25519)
+calculate_trust(const std::string &user_id, const MegolmSessionIndex &index)
{
auto status = cache::client()->verificationStatus(user_id);
+ auto megolmData = cache::client()->getMegolmSessionData(index);
crypto::Trust trustlevel = crypto::Trust::Unverified;
- if (status.verified_device_keys.count(curve25519))
- trustlevel = status.verified_device_keys.at(curve25519);
+
+ if (megolmData && megolmData->trusted &&
+ status.verified_device_keys.count(index.sender_key))
+ trustlevel = status.verified_device_keys.at(index.sender_key);
return trustlevel;
}
diff --git a/src/Olm.h b/src/Olm.h
index ab86ca00..eb60ae3a 100644
--- a/src/Olm.h
+++ b/src/Olm.h
@@ -70,6 +70,8 @@ create_inbound_megolm_session(const mtx::events::DeviceEvent<mtx::events::msg::R
void
import_inbound_megolm_session(
const mtx::events::DeviceEvent<mtx::events::msg::ForwardedRoomKey> &roomKey);
+void
+lookup_keybackup(const std::string room, const std::string session_id);
nlohmann::json
handle_pre_key_olm_message(const std::string &sender,
@@ -87,7 +89,7 @@ decryptEvent(const MegolmSessionIndex &index,
const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event,
bool dont_write_db = false);
crypto::Trust
-calculate_trust(const std::string &user_id, const std::string &curve25519);
+calculate_trust(const std::string &user_id, const MegolmSessionIndex &index);
void
mark_keys_as_published();
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index f67c5e2d..ab1e442c 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -124,6 +124,7 @@ UserSettings::load(std::optional<QString> profile)
.toBool();
onlyShareKeysWithVerifiedUsers_ =
settings.value(prefix + "user/only_share_keys_with_verified_users", false).toBool();
+ useOnlineKeyBackup_ = settings.value(prefix + "user/online_key_backup", true).toBool();
disableCertificateValidation_ =
settings.value("disable_certificate_validation", false).toBool();
@@ -426,6 +427,17 @@ UserSettings::setShareKeysWithTrustedUsers(bool shareKeys)
}
void
+UserSettings::setUseOnlineKeyBackup(bool useBackup)
+{
+ if (useBackup == useOnlineKeyBackup_)
+ return;
+
+ useOnlineKeyBackup_ = useBackup;
+ emit useOnlineKeyBackupChanged(useBackup);
+ save();
+}
+
+void
UserSettings::setRingtone(QString ringtone)
{
if (ringtone == ringtone_)
@@ -664,6 +676,7 @@ UserSettings::save()
shareKeysWithTrustedUsers_);
settings.setValue(prefix + "user/only_share_keys_with_verified_users",
onlyShareKeysWithVerifiedUsers_);
+ settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
settings.setValue("disable_certificate_validation", disableCertificateValidation_);
@@ -725,6 +738,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
privacyScreen_ = new Toggle{this};
onlyShareKeysWithVerifiedUsers_ = new Toggle(this);
shareKeysWithTrustedUsers_ = new Toggle(this);
+ useOnlineKeyBackup_ = new Toggle(this);
groupViewToggle_ = new Toggle{this};
timelineButtonsToggle_ = new Toggle{this};
typingNotifications_ = new Toggle{this};
@@ -756,6 +770,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
privacyScreen_->setChecked(settings_->privacyScreen());
onlyShareKeysWithVerifiedUsers_->setChecked(settings_->onlyShareKeysWithVerifiedUsers());
shareKeysWithTrustedUsers_->setChecked(settings_->shareKeysWithTrustedUsers());
+ useOnlineKeyBackup_->setChecked(settings_->useOnlineKeyBackup());
groupViewToggle_->setChecked(settings_->groupView());
timelineButtonsToggle_->setChecked(settings_->buttonsInTimeline());
typingNotifications_->setChecked(settings_->typingNotifications());
@@ -1033,6 +1048,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
shareKeysWithTrustedUsers_,
tr("Automatically replies to key requests from other users, if they are verified, "
"even if that device shouldn't have access to those keys otherwise."));
+ boxWrap(tr("Online Key Backup"),
+ useOnlineKeyBackup_,
+ tr("Download message encryption keys from and upload to the encrypted online key "
+ "backup."));
formLayout_->addRow(new HorizontalLine{this});
formLayout_->addRow(sessionKeysLabel, sessionKeysLayout);
formLayout_->addRow(crossSigningKeysLabel, crossSigningKeysLayout);
@@ -1208,6 +1227,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
settings_->setShareKeysWithTrustedUsers(enabled);
});
+ connect(useOnlineKeyBackup_, &Toggle::toggled, this, [this](bool enabled) {
+ settings_->setUseOnlineKeyBackup(enabled);
+ });
+
connect(avatarCircles_, &Toggle::toggled, this, [this](bool enabled) {
settings_->setAvatarCircles(enabled);
});
@@ -1298,6 +1321,7 @@ UserSettingsPage::showEvent(QShowEvent *)
privacyScreen_->setState(settings_->privacyScreen());
onlyShareKeysWithVerifiedUsers_->setState(settings_->onlyShareKeysWithVerifiedUsers());
shareKeysWithTrustedUsers_->setState(settings_->shareKeysWithTrustedUsers());
+ useOnlineKeyBackup_->setState(settings_->useOnlineKeyBackup());
avatarCircles_->setState(settings_->avatarCircles());
typingNotifications_->setState(settings_->typingNotifications());
sortByImportance_->setState(settings_->sortByImportance());
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index 84940e47..ab9c9a3b 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -93,6 +93,8 @@ class UserSettings : public QObject
setOnlyShareKeysWithVerifiedUsers NOTIFY onlyShareKeysWithVerifiedUsersChanged)
Q_PROPERTY(bool shareKeysWithTrustedUsers READ shareKeysWithTrustedUsers WRITE
setShareKeysWithTrustedUsers NOTIFY shareKeysWithTrustedUsersChanged)
+ Q_PROPERTY(bool useOnlineKeyBackup READ useOnlineKeyBackup WRITE setUseOnlineKeyBackup
+ NOTIFY useOnlineKeyBackupChanged)
Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged)
Q_PROPERTY(
@@ -159,6 +161,7 @@ public:
void setUseStunServer(bool state);
void setOnlyShareKeysWithVerifiedUsers(bool state);
void setShareKeysWithTrustedUsers(bool state);
+ void setUseOnlineKeyBackup(bool state);
void setProfile(QString profile);
void setUserId(QString userId);
void setAccessToken(QString accessToken);
@@ -215,6 +218,7 @@ public:
bool useStunServer() const { return useStunServer_; }
bool shareKeysWithTrustedUsers() const { return shareKeysWithTrustedUsers_; }
bool onlyShareKeysWithVerifiedUsers() const { return onlyShareKeysWithVerifiedUsers_; }
+ bool useOnlineKeyBackup() const { return useOnlineKeyBackup_; }
QString profile() const { return profile_; }
QString userId() const { return userId_; }
QString accessToken() const { return accessToken_; }
@@ -261,6 +265,7 @@ signals:
void useStunServerChanged(bool state);
void onlyShareKeysWithVerifiedUsersChanged(bool state);
void shareKeysWithTrustedUsersChanged(bool state);
+ void useOnlineKeyBackupChanged(bool state);
void profileChanged(QString profile);
void userIdChanged(QString userId);
void accessTokenChanged(QString accessToken);
@@ -293,6 +298,7 @@ private:
int privacyScreenTimeout_;
bool shareKeysWithTrustedUsers_;
bool onlyShareKeysWithVerifiedUsers_;
+ bool useOnlineKeyBackup_;
bool mobileMode_;
int timelineMaxWidth_;
int roomListWidth_;
@@ -384,6 +390,7 @@ private:
QSpinBox *privacyScreenTimeout_;
Toggle *shareKeysWithTrustedUsers_;
Toggle *onlyShareKeysWithVerifiedUsers_;
+ Toggle *useOnlineKeyBackup_;
Toggle *mobileMode_;
QLabel *deviceFingerprintValue_;
QLabel *deviceIdValue_;
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 742f8dbb..8860bc75 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -643,10 +643,7 @@ EventStore::decryptEvent(const IdIndex &idx,
if (auto cachedEvent = decryptedEvents_.object(idx))
return cachedEvent;
- MegolmSessionIndex index;
- index.room_id = room_id_;
- index.session_id = e.content.session_id;
- index.sender_key = e.content.sender_key;
+ MegolmSessionIndex index(room_id_, e.content);
auto asCacheEntry = [&idx](olm::DecryptionResult &&event) {
auto event_ptr = new olm::DecryptionResult(std::move(event));
@@ -726,6 +723,7 @@ EventStore::requestSession(const mtx::events::EncryptedEvent<mtx::events::msg::E
qint64 delay = manual ? 60 : (60 * 10);
if (r.requested_at + delay < QDateTime::currentSecsSinceEpoch()) {
r.requested_at = QDateTime::currentSecsSinceEpoch();
+ olm::lookup_keybackup(room_id_, ev.content.session_id);
olm::send_key_request_for(copy, r.request_id);
}
} else {
@@ -733,6 +731,7 @@ EventStore::requestSession(const mtx::events::EncryptedEvent<mtx::events::msg::E
request.request_id = "key_request." + http::client()->generate_txn_id();
request.requested_at = QDateTime::currentSecsSinceEpoch();
request.events.push_back(copy);
+ olm::lookup_keybackup(room_id_, ev.content.session_id);
olm::send_key_request_for(copy, request.request_id);
pending_key_requests[ev.content.session_id] = request;
}
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 79c28edf..88d575fa 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -641,8 +641,9 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
if (auto encrypted =
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
&*encrypted_event)) {
- return olm::calculate_trust(encrypted->sender,
- encrypted->content.sender_key);
+ return olm::calculate_trust(
+ encrypted->sender,
+ MegolmSessionIndex(room_id_.toStdString(), encrypted->content));
}
}
return crypto::Trust::Unverified;
@@ -840,10 +841,7 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
for (auto e : timeline.events) {
if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
- MegolmSessionIndex index;
- index.room_id = room_id_.toStdString();
- index.session_id = encryptedEvent->content.session_id;
- index.sender_key = encryptedEvent->content.sender_key;
+ MegolmSessionIndex index(room_id_.toStdString(), encryptedEvent->content);
auto result = olm::decryptEvent(index, *encryptedEvent);
if (result.event)
|