Allow downloading keys from key backup

This commit is contained in:
Nicolas Werner 2021-08-17 03:23:51 +02:00
parent e5dea361c0
commit 56db0dbc7d
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
15 changed files with 342 additions and 34 deletions

View file

@ -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) {
@ -856,6 +858,97 @@ mark_keys_as_published()
cache::saveOlmAccount(olm::client()->save(STORAGE_SECRET_KEY));
}
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,
@ -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;
}