summary refs log tree commit diff
path: root/src/Cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cache.cpp')
-rw-r--r--src/Cache.cpp178
1 files changed, 146 insertions, 32 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index 63f6e426..d6da03c6 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -3184,6 +3184,28 @@ Cache::updateUserKeys(const std::string &sync_token, const mtx::responses::Query } txn.commit(); + + std::map<std::string, VerificationStatus> tmp; + const auto local_user = utils::localUser().toStdString(); + + { + std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx); + for (auto &[user_id, update] : updates) { + if (user_id == local_user) { + std::swap(tmp, verification_storage.status); + } else { + verification_storage.status.erase(user_id); + } + } + } + for (auto &[user_id, update] : updates) { + if (user_id == local_user) { + for (const auto &[user, status] : tmp) + emit verificationStatusChanged(user); + } else { + emit verificationStatusChanged(user_id); + } + } } void @@ -3236,23 +3258,19 @@ Cache::markUserKeysOutOfDate(lmdb::txn &txn, void to_json(json &j, const VerificationCache &info) { - j["verified_master_key"] = info.verified_master_key; - j["cross_verified"] = info.cross_verified; - j["device_verified"] = info.device_verified; - j["device_blocked"] = info.device_blocked; + j["device_verified"] = info.device_verified; + j["device_blocked"] = info.device_blocked; } void from_json(const json &j, VerificationCache &info) { - info.verified_master_key = j.at("verified_master_key"); - info.cross_verified = j.at("cross_verified").get<std::vector<std::string>>(); - info.device_verified = j.at("device_verified").get<std::vector<std::string>>(); - info.device_blocked = j.at("device_blocked").get<std::vector<std::string>>(); + info.device_verified = j.at("device_verified").get<std::vector<std::string>>(); + info.device_blocked = j.at("device_blocked").get<std::vector<std::string>>(); } std::optional<VerificationCache> -Cache::verificationStatus(const std::string &user_id) +Cache::verificationCache(const std::string &user_id) { lmdb::val verifiedVal; @@ -3298,6 +3316,23 @@ Cache::markDeviceVerified(const std::string &user_id, const std::string &key) txn.commit(); } catch (std::exception &) { } + + const auto local_user = utils::localUser().toStdString(); + std::map<std::string, VerificationStatus> tmp; + { + std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx); + if (user_id == local_user) { + std::swap(tmp, verification_storage.status); + } else { + verification_storage.status.erase(user_id); + } + } + if (user_id == local_user) { + for (const auto &[user, status] : tmp) + emit verificationStatusChanged(user); + } else { + emit verificationStatusChanged(user_id); + } } void @@ -3325,27 +3360,112 @@ Cache::markDeviceUnverified(const std::string &user_id, const std::string &key) txn.commit(); } catch (std::exception &) { } + + const auto local_user = utils::localUser().toStdString(); + std::map<std::string, VerificationStatus> tmp; + { + std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx); + if (user_id == local_user) { + std::swap(tmp, verification_storage.status); + } else { + verification_storage.status.erase(user_id); + } + } + if (user_id == local_user) { + for (const auto &[user, status] : tmp) + emit verificationStatusChanged(user); + } else { + emit verificationStatusChanged(user_id); + } } -void -Cache::markMasterKeyVerified(const std::string &user_id, const std::string &key) +VerificationStatus +Cache::verificationStatus(const std::string &user_id) { - lmdb::val val; + std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx); + if (verification_storage.status.count(user_id)) + return verification_storage.status.at(user_id); - auto txn = lmdb::txn::begin(env_); - auto db = getVerificationDb(txn); + VerificationStatus status; + + if (auto verifCache = verificationCache(user_id)) { + status.verified_devices = verifCache->device_verified; + } + + const auto local_user = utils::localUser().toStdString(); + + if (user_id == local_user) + status.verified_devices.push_back(http::client()->device_id()); + + verification_storage.status[user_id] = status; + + auto verifyAtLeastOneSig = [](const auto &toVerif, + const std::map<std::string, std::string> &keys, + const std::string &keyOwner) { + if (!toVerif.signatures.count(keyOwner)) + return false; + + for (const auto &[key_id, signature] : toVerif.signatures.at(keyOwner)) { + if (!keys.count(key_id)) + continue; + + if (mtx::crypto::ed25519_verify_signature( + keys.at(key_id), json(toVerif), signature)) + return true; + } + return false; + }; try { - VerificationCache verified_state; - auto res = lmdb::dbi_get(txn, db, lmdb::val(user_id), val); - if (res) { - verified_state = json::parse(std::string_view(val.data(), val.size())); + // for local user verify this device_key -> our master_key -> our self_signing_key + // -> our device_keys + // + // for other user verify this device_key -> our master_key -> our user_signing_key + // -> their master_key -> their self_signing_key -> their device_keys + // + // This means verifying the other user adds 2 extra steps,verifying our user_signing + // key and their master key + auto ourKeys = userKeys(local_user); + auto theirKeys = userKeys(user_id); + if (!ourKeys || !theirKeys) + return status; + + if (!mtx::crypto::ed25519_verify_signature( + olm::client()->identity_keys().ed25519, + json(ourKeys->master_keys), + ourKeys->master_keys.signatures.at(local_user) + .at("ed25519:" + http::client()->device_id()))) + return status; + + auto master_keys = ourKeys->master_keys.keys; + + if (user_id != local_user) { + if (!verifyAtLeastOneSig( + ourKeys->user_signing_keys, master_keys, local_user)) + return status; + + if (!verifyAtLeastOneSig( + theirKeys->master_keys, ourKeys->user_signing_keys.keys, local_user)) + return status; + + master_keys = theirKeys->master_keys.keys; } - verified_state.verified_master_key = key; - lmdb::dbi_put(txn, db, lmdb::val(user_id), lmdb::val(json(verified_state).dump())); - txn.commit(); + status.user_verified = true; + + if (!verifyAtLeastOneSig(theirKeys->self_signing_keys, master_keys, user_id)) + return status; + + for (const auto &[device, device_key] : theirKeys->device_keys) { + if (verifyAtLeastOneSig( + device_key, theirKeys->self_signing_keys.keys, user_id)) + status.verified_devices.push_back(device_key.device_id); + } + + verification_storage.status[user_id] = status; + return status; } catch (std::exception &) { + return status; } } @@ -3551,28 +3671,22 @@ updateUserKeys(const std::string &sync_token, const mtx::responses::QueryKeys &k } // device & user verification cache -std::optional<VerificationCache> +std::optional<VerificationStatus> verificationStatus(const std::string &user_id) { return instance_->verificationStatus(user_id); } void -markDeviceVerified(const std::string &user_id, const std::string &key) -{ - instance_->markDeviceVerified(user_id, key); -} - -void -markDeviceUnverified(const std::string &user_id, const std::string &key) +markDeviceVerified(const std::string &user_id, const std::string &device) { - instance_->markDeviceUnverified(user_id, key); + instance_->markDeviceVerified(user_id, device); } void -markMasterKeyVerified(const std::string &user_id, const std::string &key) +markDeviceUnverified(const std::string &user_id, const std::string &device) { - instance_->markMasterKeyVerified(user_id, key); + instance_->markDeviceUnverified(user_id, device); } std::vector<std::string>