diff --git a/src/Olm.cpp b/src/Olm.cpp index c0360e1c..9e6c73e0 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp @@ -32,6 +32,11 @@ constexpr auto MEGOLM_ALGO = "m.megolm.v1.aes-sha2"; } namespace olm { +static void +backup_session_key(const MegolmSessionIndex &idx, + const GroupSessionData &data, + mtx::crypto::InboundGroupSessionPtr &session); + void 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; auto megolm_session = olm::client()->init_inbound_group_session(session_key); + backup_session_key(index, session_data, megolm_session); cache::saveInboundMegolmSession( index, std::move(megolm_session), session_data); } @@ -801,6 +807,7 @@ create_inbound_megolm_session(const mtx::events::DeviceEventinit_inbound_group_session(roomKey.content.session_key); + backup_session_key(index, data, megolm_session); cache::saveInboundMegolmSession(index, std::move(megolm_session), data); } catch (const lmdb::error &e) { nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what()); @@ -843,6 +850,7 @@ import_inbound_megolm_session( data.trusted = true; } + backup_session_key(index, data, megolm_session); cache::saveInboundMegolmSession(index, std::move(megolm_session), data); } catch (const lmdb::error &e) { 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); } +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(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 mark_keys_as_published() { diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 82b29456..fa94616f 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -1234,7 +1234,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge tr("Enable online key backup"), tr("The Nheko authors recommend not enabling online key backup until " "symmetric online key backup is available. Enable anyway?")) != - QMessageBox::StandardButton::NoButton) { + QMessageBox::StandardButton::Yes) { useOnlineKeyBackup_->setState(false); return; }