Implement key backup upload

This commit is contained in:
Nicolas Werner 2021-08-26 03:42:58 +02:00
parent 23697e28a3
commit d02e77f69a
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
2 changed files with 77 additions and 1 deletions

View file

@ -32,6 +32,11 @@ constexpr auto MEGOLM_ALGO = "m.megolm.v1.aes-sha2";
} }
namespace olm { namespace olm {
static void
backup_session_key(const MegolmSessionIndex &idx,
const GroupSessionData &data,
mtx::crypto::InboundGroupSessionPtr &session);
void void
from_json(const nlohmann::json &obj, OlmMessage &msg) from_json(const nlohmann::json &obj, OlmMessage &msg)
{ {
@ -682,6 +687,7 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
index.sender_key = olm::client()->identity_keys().curve25519; index.sender_key = olm::client()->identity_keys().curve25519;
auto megolm_session = auto megolm_session =
olm::client()->init_inbound_group_session(session_key); olm::client()->init_inbound_group_session(session_key);
backup_session_key(index, session_data, megolm_session);
cache::saveInboundMegolmSession( cache::saveInboundMegolmSession(
index, std::move(megolm_session), session_data); index, std::move(megolm_session), session_data);
} }
@ -801,6 +807,7 @@ create_inbound_megolm_session(const mtx::events::DeviceEvent<mtx::events::msg::R
auto megolm_session = auto megolm_session =
olm::client()->init_inbound_group_session(roomKey.content.session_key); olm::client()->init_inbound_group_session(roomKey.content.session_key);
backup_session_key(index, data, megolm_session);
cache::saveInboundMegolmSession(index, std::move(megolm_session), data); cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
} catch (const lmdb::error &e) { } catch (const lmdb::error &e) {
nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what()); nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
@ -843,6 +850,7 @@ import_inbound_megolm_session(
data.trusted = true; data.trusted = true;
} }
backup_session_key(index, data, megolm_session);
cache::saveInboundMegolmSession(index, std::move(megolm_session), data); cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
} catch (const lmdb::error &e) { } catch (const lmdb::error &e) {
nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what()); nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
@ -858,6 +866,74 @@ import_inbound_megolm_session(
ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id); ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
} }
void
backup_session_key(const MegolmSessionIndex &idx,
const GroupSessionData &data,
mtx::crypto::InboundGroupSessionPtr &session)
{
try {
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));
auto public_key =
mtx::crypto::CURVE25519_public_key_from_private(sessionDecryptionKey);
mtx::responses::backup::SessionData sessionData;
sessionData.algorithm = mtx::crypto::MEGOLM_ALGO;
sessionData.forwarding_curve25519_key_chain = data.forwarding_curve25519_key_chain;
sessionData.sender_claimed_keys["ed25519"] = data.sender_claimed_ed25519_key;
sessionData.sender_key = idx.sender_key;
sessionData.session_key = mtx::crypto::export_session(session.get(), -1);
auto encrypt_session = mtx::crypto::encrypt_session(sessionData, public_key);
mtx::responses::backup::SessionBackup bk;
bk.first_message_index = olm_inbound_group_session_first_known_index(session.get());
bk.forwarded_count = data.forwarding_curve25519_key_chain.size();
bk.is_verified = false;
bk.session_data = std::move(encrypt_session);
http::client()->put_room_keys(
backupVersion->version,
idx.room_id,
idx.session_id,
bk,
[idx](const mtx::http::RequestErr &err) {
if (err) {
nhlog::net()->warn(
"failed to backup session key ({}:{}): {} ({})",
idx.room_id,
idx.session_id,
err->matrix_error.error,
static_cast<int>(err->status_code));
} else {
nhlog::crypto()->debug(
"backed up session key ({}:{})", idx.room_id, idx.session_id);
}
});
} catch (std::exception &e) {
nhlog::net()->warn("failed to backup session key: {}", e.what());
}
}
void void
mark_keys_as_published() mark_keys_as_published()
{ {

View file

@ -1234,7 +1234,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidge
tr("Enable online key backup"), tr("Enable online key backup"),
tr("The Nheko authors recommend not enabling online key backup until " tr("The Nheko authors recommend not enabling online key backup until "
"symmetric online key backup is available. Enable anyway?")) != "symmetric online key backup is available. Enable anyway?")) !=
QMessageBox::StandardButton::NoButton) { QMessageBox::StandardButton::Yes) {
useOnlineKeyBackup_->setState(false); useOnlineKeyBackup_->setState(false);
return; return;
} }