mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 03:00:46 +03:00
Protect against replay attacks
This commit is contained in:
parent
72bbad7485
commit
b73bd2859c
4 changed files with 29 additions and 3 deletions
|
@ -158,7 +158,7 @@ Cache::isHiddenEvent(lmdb::txn &txn,
|
|||
index.session_id = encryptedEvent->content.session_id;
|
||||
index.sender_key = encryptedEvent->content.sender_key;
|
||||
|
||||
auto result = olm::decryptEvent(index, *encryptedEvent);
|
||||
auto result = olm::decryptEvent(index, *encryptedEvent, true);
|
||||
if (!result.error)
|
||||
e = result.event.value();
|
||||
}
|
||||
|
@ -4294,6 +4294,8 @@ to_json(nlohmann::json &obj, const GroupSessionData &msg)
|
|||
obj["forwarding_curve25519_key_chain"] = msg.forwarding_curve25519_key_chain;
|
||||
|
||||
obj["currently"] = msg.currently;
|
||||
|
||||
obj["indices"] = msg.indices;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -4307,6 +4309,8 @@ from_json(const nlohmann::json &obj, GroupSessionData &msg)
|
|||
obj.value("forwarding_curve25519_key_chain", std::vector<std::string>{});
|
||||
|
||||
msg.currently = obj.value("currently", SharedWithUsers{});
|
||||
|
||||
msg.indices = obj.value("indices", std::map<uint32_t, std::string>());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -50,6 +50,9 @@ struct GroupSessionData
|
|||
std::string sender_claimed_ed25519_key;
|
||||
std::vector<std::string> forwarding_curve25519_key_chain;
|
||||
|
||||
//! map from index to event_id to check for replay attacks
|
||||
std::map<uint32_t, std::string> indices;
|
||||
|
||||
// who has access to this session.
|
||||
// Rotate, when a user leaves the room and share, when a user gets added.
|
||||
SharedWithUsers currently;
|
||||
|
|
19
src/Olm.cpp
19
src/Olm.cpp
|
@ -1028,7 +1028,8 @@ send_megolm_key_to_device(const std::string &user_id,
|
|||
|
||||
DecryptionResult
|
||||
decryptEvent(const MegolmSessionIndex &index,
|
||||
const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event)
|
||||
const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event,
|
||||
bool dont_write_db)
|
||||
{
|
||||
try {
|
||||
if (!cache::client()->inboundMegolmSessionExists(index)) {
|
||||
|
@ -1043,10 +1044,26 @@ decryptEvent(const MegolmSessionIndex &index,
|
|||
std::string msg_str;
|
||||
try {
|
||||
auto session = cache::client()->getInboundMegolmSession(index);
|
||||
auto sessionData =
|
||||
cache::client()->getMegolmSessionData(index).value_or(GroupSessionData{});
|
||||
|
||||
auto res =
|
||||
olm::client()->decrypt_group_message(session.get(), event.content.ciphertext);
|
||||
msg_str = std::string((char *)res.data.data(), res.data.size());
|
||||
|
||||
if (!event.event_id.empty() && event.event_id[0] == '$') {
|
||||
auto oldIdx = sessionData.indices.find(res.message_index);
|
||||
if (oldIdx != sessionData.indices.end()) {
|
||||
if (oldIdx->second != event.event_id)
|
||||
return {DecryptionErrorCode::ReplayAttack,
|
||||
std::nullopt,
|
||||
std::nullopt};
|
||||
} else if (!dont_write_db) {
|
||||
sessionData.indices[res.message_index] = event.event_id;
|
||||
cache::client()->saveInboundMegolmSession(
|
||||
index, std::move(session), sessionData);
|
||||
}
|
||||
}
|
||||
} catch (const lmdb::error &e) {
|
||||
return {DecryptionErrorCode::DbError, e.what(), std::nullopt};
|
||||
} catch (const mtx::crypto::olm_exception &e) {
|
||||
|
|
|
@ -81,9 +81,11 @@ encrypt_group_message(const std::string &room_id,
|
|||
const std::string &device_id,
|
||||
nlohmann::json body);
|
||||
|
||||
//! Decrypt an event. Use dont_write_db to prevent db writes when already in a write transaction.
|
||||
DecryptionResult
|
||||
decryptEvent(const MegolmSessionIndex &index,
|
||||
const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event);
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue