summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-05-07 12:19:46 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-05-07 17:01:57 +0200
commit0d0709ccd37ef2f689c9d22a20994ce8d423e18b (patch)
tree110a1e0692184d34a3535dce1f8d3d99c1d70194 /src
parentTranslated using Weblate (Spanish) (diff)
downloadnheko-0d0709ccd37ef2f689c9d22a20994ce8d423e18b.tar.xz
Show verification status next to messages
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp21
-rw-r--r--src/CacheCryptoStructs.h20
-rw-r--r--src/DeviceVerificationFlow.cpp2
-rw-r--r--src/Olm.cpp12
-rw-r--r--src/Olm.h3
-rw-r--r--src/timeline/TimelineModel.cpp16
-rw-r--r--src/timeline/TimelineModel.h1
-rw-r--r--src/timeline/TimelineViewManager.cpp2
-rw-r--r--src/ui/UserProfile.cpp2
-rw-r--r--src/ui/UserProfile.h12
10 files changed, 77 insertions, 14 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index 0de790ac..4022ce85 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -3666,8 +3666,11 @@ Cache::verificationStatus(const std::string &user_id) const auto local_user = utils::localUser().toStdString(); - if (user_id == local_user) + crypto::Trust trustlevel = crypto::Trust::Unverified; + if (user_id == local_user) { status.verified_devices.push_back(http::client()->device_id()); + trustlevel = crypto::Trust::Verified; + } verification_storage.status[user_id] = status; @@ -3723,16 +3726,24 @@ Cache::verificationStatus(const std::string &user_id) master_keys = theirKeys->master_keys.keys; } - status.user_verified = true; + trustlevel = crypto::Trust::Verified; + status.user_verified = crypto::Trust::Verified; if (!verifyAtLeastOneSig(theirKeys->self_signing_keys, master_keys, user_id)) return status; for (const auto &[device, device_key] : theirKeys->device_keys) { (void)device; - if (verifyAtLeastOneSig( - device_key, theirKeys->self_signing_keys.keys, user_id)) - status.verified_devices.push_back(device_key.device_id); + try { + auto identkey = + device_key.keys.at("curve25519:" + device_key.device_id); + if (verifyAtLeastOneSig( + device_key, theirKeys->self_signing_keys.keys, user_id)) { + status.verified_devices.push_back(device_key.device_id); + status.verified_device_keys[identkey] = trustlevel; + } + } catch (...) { + } } verification_storage.status[user_id] = status; diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h
index c884107e..b665be86 100644 --- a/src/CacheCryptoStructs.h +++ b/src/CacheCryptoStructs.h
@@ -4,12 +4,28 @@ #pragma once +#include <QObject> + #include <map> #include <mutex> +#include <mtx/events/encrypted.hpp> #include <mtx/responses/crypto.hpp> #include <mtxclient/crypto/objects.hpp> +namespace crypto { +Q_NAMESPACE +//! How much a participant is trusted. +enum Trust +{ + Unverified, //! Device unverified or master key changed. + TOFU, //! Device is signed by the sender, but the user is not verified, but they never + //! changed the master key. + Verified, //! User was verified and has crosssigned this device or device is verified. +}; +Q_ENUM_NS(Trust) +} + struct DeviceAndMasterKeys { // map from device id or master key id to message_index @@ -87,9 +103,11 @@ from_json(const nlohmann::json &obj, StoredOlmSession &msg); struct VerificationStatus { //! True, if the users master key is verified - bool user_verified = false; + crypto::Trust user_verified = crypto::Trust::Unverified; //! List of all devices marked as verified std::vector<std::string> verified_devices; + //! Map from sender key/curve25519 to trust status + std::map<std::string, crypto::Trust> verified_device_keys; }; //! In memory cache of verification status diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp
index f7fb6c35..cd375cc9 100644 --- a/src/DeviceVerificationFlow.cpp +++ b/src/DeviceVerificationFlow.cpp
@@ -78,7 +78,7 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *, if (auto status = cache::verificationStatus(http::client()->user_id().to_string()); - status && status->user_verified) + status && status->user_verified == crypto::Trust::Verified) this->our_trusted_master_key = res.master_keys.keys.begin()->second; }); diff --git a/src/Olm.cpp b/src/Olm.cpp
index b218ba2c..d08c1b3e 100644 --- a/src/Olm.cpp +++ b/src/Olm.cpp
@@ -939,7 +939,6 @@ decryptEvent(const MegolmSessionIndex &index, } // TODO: Lookup index,event_id,origin_server_ts tuple for replay attack errors - // TODO: Verify sender_key std::string msg_str; try { @@ -976,6 +975,17 @@ decryptEvent(const MegolmSessionIndex &index, return {std::nullopt, std::nullopt, std::move(te.data)}; } +crypto::Trust +calculate_trust(const std::string &user_id, const std::string &curve25519) +{ + auto status = cache::client()->verificationStatus(user_id); + crypto::Trust trustlevel = crypto::Trust::Unverified; + if (status.verified_device_keys.count(curve25519)) + trustlevel = status.verified_device_keys.at(curve25519); + + return trustlevel; +} + //! Send encrypted to device messages, targets is a map from userid to device ids or {} for all //! devices void diff --git a/src/Olm.h b/src/Olm.h
index bcb486a3..d356cb55 100644 --- a/src/Olm.h +++ b/src/Olm.h
@@ -34,6 +34,7 @@ struct DecryptionResult { std::optional<DecryptionErrorCode> error; std::optional<std::string> error_message; + std::optional<mtx::events::collections::TimelineEvents> event; }; @@ -83,6 +84,8 @@ encrypt_group_message(const std::string &room_id, DecryptionResult decryptEvent(const MegolmSessionIndex &index, const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event); +crypto::Trust +calculate_trust(const std::string &user_id, const std::string &curve25519); void mark_keys_as_published(); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index a1e9ac0c..5fa28234 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp
@@ -407,6 +407,7 @@ TimelineModel::roleNames() const {IsEdited, "isEdited"}, {IsEditable, "isEditable"}, {IsEncrypted, "isEncrypted"}, + {Trustlevel, "trustlevel"}, {IsRoomEncrypted, "isRoomEncrypted"}, {ReplyTo, "replyTo"}, {Reactions, "reactions"}, @@ -575,6 +576,21 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>( *encrypted_event); } + + case Trustlevel: { + auto id = event_id(event); + auto encrypted_event = events.get(id, id, false); + if (encrypted_event) { + 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 crypto::Trust::Unverified; + } + case IsRoomEncrypted: { return cache::isRoomEncrypted(room_id_.toStdString()); } diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index caeb25cf..92fccd2d 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h
@@ -196,6 +196,7 @@ public: IsEdited, IsEditable, IsEncrypted, + Trustlevel, IsRoomEncrypted, ReplyTo, Reactions, diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index decd245c..628f3c31 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp
@@ -164,6 +164,8 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par 0, "MtxEvent", "Can't instantiate enum!"); + qmlRegisterUncreatableMetaObject( + crypto::staticMetaObject, "im.nheko", 1, 0, "Crypto", "Can't instantiate enum!"); qmlRegisterUncreatableMetaObject(verification::staticMetaObject, "im.nheko", 1, diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index b5feb353..0f330964 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp
@@ -135,7 +135,7 @@ UserProfile::isGlobalUserProfile() const return roomid_ == ""; } -bool +crypto::Trust UserProfile::getUserStatus() { return isUserVerified; diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index aa7266ab..bf71d0de 100644 --- a/src/ui/UserProfile.h +++ b/src/ui/UserProfile.h
@@ -11,6 +11,8 @@ #include <mtx/responses.hpp> #include <mtx/responses/common.hpp> +#include "CacheCryptoStructs.h" + namespace verification { Q_NAMESPACE @@ -90,7 +92,7 @@ class UserProfile : public QObject Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged) Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList CONSTANT) Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT) - Q_PROPERTY(bool isUserVerified READ getUserStatus NOTIFY userStatusChanged) + Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged) Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged) Q_PROPERTY( bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged) @@ -108,7 +110,7 @@ public: QString displayName(); QString avatarUrl(); bool isGlobalUserProfile() const; - bool getUserStatus(); + crypto::Trust getUserStatus(); bool userVerificationEnabled() const; bool isSelf() const; bool isLoading() const; @@ -147,9 +149,9 @@ private: QString globalUsername; QString globalAvatarUrl; DeviceInfoModel deviceList_; - bool isUserVerified = false; - bool hasMasterKey = false; - bool isLoading_ = false; + crypto::Trust isUserVerified = crypto::Trust::Unverified; + bool hasMasterKey = false; + bool isLoading_ = false; TimelineViewManager *manager; TimelineModel *model; };