Skip to content

Commit

Permalink
Fix rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
TobiasFella committed May 29, 2023
1 parent 143201c commit f750922
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 94 deletions.
43 changes: 8 additions & 35 deletions Quotient/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1911,38 +1911,17 @@ bool Connection::isKnownE2eeCapableDevice(const QString& userId, const QString&

bool Connection::hasConflictingDeviceIdsAndCrossSigningKeys(const QString& userId)
{
auto devices = devicesForUser(userId);

auto selfQuery = database()->prepareQuery("SELECT key FROM self_signing_keys WHERE userId=:userId;"_ls);
selfQuery.bindValue(":userId"_ls, userId);
database()->execute(selfQuery);
if (!selfQuery.next()) {
return false;
}
if (devices.contains(selfQuery.value("key"_ls).toString())) {
return true;
}

auto masterQuery = database()->prepareQuery("SELECT key FROM master_keys WHERE userId=:userId;"_ls);
masterQuery.bindValue(":userId"_ls, userId);
database()->execute(masterQuery);
if (!masterQuery.next()) {
return false;
}
if (devices.contains(masterQuery.value("key"_ls).toString())) {
return true;
if (d->encryptionData) {
d->encryptionData->hasConflictingDeviceIdsAndCrossSigningKeys(userId);
}
return true;
}

auto userQuery = database()->prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId;"_ls);
userQuery.bindValue(":userId"_ls, userId);
database()->execute(userQuery);
if (!userQuery.next()) {
return false;
}
if (devices.contains(userQuery.value("key"_ls).toString())) {
return true;
void Connection::reloadDevices()
{
if (d->encryptionData) {
reloadDevices();
}
return false;
}
#endif

Expand All @@ -1954,9 +1933,3 @@ Connection* Connection::makeMockConnection(const QString& mxId,
c->d->completeSetup(mxId, true);
return c;
}

void Connection::reloadDevices()
{
d->outdatedUsers = d->trackedUsers;
d->loadOutdatedUserDevices();
}
2 changes: 1 addition & 1 deletion Quotient/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,9 @@ class QUOTIENT_API Connection : public QObject {
Q_INVOKABLE bool isQueryingKeys() const;
QString masterKeyForUser(const QString& userId) const;
bool isUserVerified(const QString& userId) const;
bool hasConflictingDeviceIdsAndCrossSigningKeys(const QString& userId);

void reloadDevices();
bool hasConflictingDeviceIdsAndCrossSigningKeys(const QString& userId);

#endif // Quotient_E2EE_ENABLED
Q_INVOKABLE Quotient::SyncJob* syncJob() const;
Expand Down
150 changes: 94 additions & 56 deletions Quotient/connectionencryptiondata_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ void ConnectionEncryptionData::saveDevicesList()
query.prepare(QStringLiteral(
"INSERT INTO tracked_devices"
"(matrixId, deviceId, curveKeyId, curveKey, edKeyId, edKey, verified, selfVerified) "
"VALUES (:matrixId, :deviceId, :curveKeyId, :curveKey, :edKeyId, :edKey, :verified, :selfVerified);"
"VALUES (:matrixId, :deviceId, :curveKeyId, :curveKey, :edKeyId, :edKey, :verified, :selfVerified);"));
for (const auto& [user, devices] : asKeyValueRange(deviceKeys)) {
for (const auto& device : devices) {
auto keys = device.keys.keys();
auto deleteQuery = database->prepareQuery("DELETE FROM tracked_devices WHERE matrixId=:matrixId AND deviceId=:deviceId;"_ls);
auto deleteQuery = database.prepareQuery("DELETE FROM tracked_devices WHERE matrixId=:matrixId AND deviceId=:deviceId;"_ls);
deleteQuery.bindValue(":matrixId"_ls, user);
deleteQuery.bindValue(":deviceId"_ls, device.deviceId);
database->execute(deleteQuery);
database.execute(deleteQuery);

auto curveKeyId = keys[0].startsWith("curve"_ls) ? keys[0]
: keys[1];
Expand Down Expand Up @@ -380,8 +380,7 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
const QHash<QString, CrossSigningKey>& masterKeys, const QHash<QString, CrossSigningKey>& selfSigningKeys,
const QHash<QString, CrossSigningKey>& userSigningKeys)
{
database->transaction();
const auto masterKeys = job->masterKeys();
database.transaction();
for (const auto &[userId, key] : asKeyValueRange(masterKeys)) {
if (key.userId != userId) {
qCWarning(E2EE) << "Master key: userId mismatch";
Expand All @@ -391,35 +390,34 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qCWarning(E2EE) << "Master key: invalid usage";
continue;
}
auto checkQuery = database->prepareQuery("SELECT * FROM master_keys WHERE userId=:userId"_ls);
auto checkQuery = database.prepareQuery("SELECT * FROM master_keys WHERE userId=:userId"_ls);
checkQuery.bindValue(":userId"_ls, key.userId);
database->execute(checkQuery);
database.execute(checkQuery);
if (checkQuery.next()) {
if (checkQuery.value("key"_ls).toString() != key.keys.values()[0]) {
qCWarning(E2EE) << "New master key for" << key.userId;
database->transaction();
auto query = database->prepareQuery(
database.transaction();
auto query = database.prepareQuery(
"UPDATE tracked_devices SET verified=0, selfVerified=0 WHERE matrixId=:matrixId;"_ls);
query.bindValue(":matrixId"_ls, userId);
database->execute(query);
query = database->prepareQuery("DELETE FROM self_signing_keys WHERE userId=:userId;"_ls);
database.execute(query);
query = database.prepareQuery("DELETE FROM self_signing_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, userId);
database->execute(query);
database->commit();
database.execute(query);
database.commit();
} else {
continue;
}
}

auto query = database->prepareQuery("DELETE FROM master_keys WHERE userId=:userId;"_ls);
auto query = database.prepareQuery("DELETE FROM master_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, userId);
database->execute(query);
query = database->prepareQuery("INSERT INTO master_keys(userId, key) VALUES(:userId, :key);"_ls);
database.execute(query);
query = database.prepareQuery("INSERT INTO master_keys(userId, key) VALUES(:userId, :key);"_ls);
query.bindValue(":userId"_ls, userId);
query.bindValue(":key"_ls, key.keys.values()[0]);
database->execute(query);
database.execute(query);
}
const auto selfSigningKeys = job->selfSigningKeys();
for (const auto &[userId, key] : asKeyValueRange(selfSigningKeys)) {
if (key.userId != userId) {
qCWarning(E2EE) << "Self signing key: userId mismatch";
Expand All @@ -429,27 +427,27 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qCWarning(E2EE) << "Self signing key: invalid usage";
continue;
}
auto masterKeyQuery = database->prepareQuery("SELECT key FROM master_keys WHERE userId=:userId"_ls);
auto masterKeyQuery = database.prepareQuery("SELECT key FROM master_keys WHERE userId=:userId"_ls);
masterKeyQuery.bindValue(":userId"_ls, userId);
database->execute(masterKeyQuery);
database.execute(masterKeyQuery);
if (!masterKeyQuery.next()) {
continue;
}
auto masterKey = masterKeyQuery.value("key"_ls).toString();

auto checkQuery = database->prepareQuery("SELECT key FROM self_signing_keys WHERE userId=:userId;"_ls);
auto checkQuery = database.prepareQuery("SELECT key FROM self_signing_keys WHERE userId=:userId;"_ls);
checkQuery.bindValue(":userId"_ls, userId);
database->execute(checkQuery);
database.execute(checkQuery);
if (checkQuery.next()) {
auto oldKey = checkQuery.value("key"_ls).toString();
if (oldKey != key.keys.values()[0]) {
qCWarning(E2EE) << "New self-signing key for" << userId << ". Marking all devices as unverified.";
database->transaction();
auto query = database->prepareQuery(
database.transaction();
auto query = database.prepareQuery(
"UPDATE tracked_devices SET verified=0, selfVerified=0 WHERE matrixId=:matrixId;"_ls);
query.bindValue(":matrixId"_ls, userId);
database->execute(query);
database->commit();
database.execute(query);
database.commit();
}
}

Expand All @@ -458,15 +456,14 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qCWarning(E2EE) << "Self signing key: failed signature verification" << userId;
continue;
}
auto query = database->prepareQuery("DELETE FROM self_signing_keys WHERE userId=:userId;"_ls);
auto query = database.prepareQuery("DELETE FROM self_signing_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, userId);
database->execute(query);
query = database->prepareQuery("INSERT INTO self_signing_keys(userId, key) VALUES(:userId, :key);"_ls);
database.execute(query);
query = database.prepareQuery("INSERT INTO self_signing_keys(userId, key) VALUES(:userId, :key);"_ls);
query.bindValue(":userId"_ls, userId);
query.bindValue(":key"_ls, key.keys.values()[0]);
database->execute(query);
database.execute(query);
}
const auto userSigningKeys = job->userSigningKeys();
for (const auto &[userId, key] : asKeyValueRange(userSigningKeys)) {
if (key.userId != userId) {
qWarning() << "User signing key: userId mismatch";
Expand All @@ -476,25 +473,25 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qWarning() << "User signing key: invalid usage";
continue;
}
auto masterKeyQuery = database->prepareQuery("SELECT key FROM master_keys WHERE userId=:userId"_ls);
auto masterKeyQuery = database.prepareQuery("SELECT key FROM master_keys WHERE userId=:userId"_ls);
masterKeyQuery.bindValue(":userId"_ls, userId);
database->execute(masterKeyQuery);
database.execute(masterKeyQuery);
if (!masterKeyQuery.next()) {
continue;
}

auto checkQuery = database->prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId"_ls);
auto checkQuery = database.prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId"_ls);
checkQuery.bindValue(":userId"_ls, userId);
database->execute(checkQuery);
database.execute(checkQuery);
if (checkQuery.next()) {
auto oldKey = checkQuery.value("key"_ls).toString();
if (oldKey != key.keys.values()[0]) {
qCWarning(E2EE) << "New user signing key; marking all master signing keys as unverified";
database->transaction();
auto query = database->prepareQuery(
database.transaction();
auto query = database.prepareQuery(
"UPDATE master_keys SET verified=0;"_ls);
database->execute(query);
database->commit();
database.execute(query);
database.commit();
}
}

Expand All @@ -504,41 +501,40 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qWarning() << "User signing key: failed signature verification" << userId;
continue;
}
auto query = database->prepareQuery("DELETE FROM user_signing_keys WHERE userId=:userId;"_ls);
auto query = database.prepareQuery("DELETE FROM user_signing_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, userId);
database->execute(query);
query = database->prepareQuery("INSERT INTO user_signing_keys(userId, key) VALUES(:userId, :key);"_ls);
database.execute(query);
query = database.prepareQuery("INSERT INTO user_signing_keys(userId, key) VALUES(:userId, :key);"_ls);
query.bindValue(":userId"_ls, userId);
query.bindValue(":key"_ls, key.keys.values()[0]);
database->execute(query);
database.execute(query);
}
database->commit();
database.commit();
if (q->isUserVerified(q->userId())) {
auto query = database->prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId;"_ls);
auto query = database.prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, q->userId());
database->execute(query);
database.execute(query);
query.next();
auto userSigningKey = query.value("key"_ls).toString();
for (const auto& masterKey : job->masterKeys()) {
for (const auto& masterKey : masterKeys) {
auto signature = masterKey.signatures[q->userId()]["ed25519:"_ls % userSigningKey].toString();
if (!signature.isEmpty()) {
if (ed25519VerifySignature(userSigningKey, toJson(masterKey), signature)) {
database->setMasterKeyVerified(masterKey.keys.values()[0]);
database.setMasterKeyVerified(masterKey.keys.values()[0]);
emit q->userVerified(masterKey.userId);
} else {
qCWarning(E2EE) << "Master key signature verification failed";
}
}
}
}
const auto data = job->deviceKeys();
for(const auto &[user, keys] : asKeyValueRange(data)) {
QHash<QString, Quotient::DeviceKeys> oldDevices = deviceKeys[user];
auto query = database->prepareQuery("SELECT * FROM self_signing_keys WHERE userId=:userId;"_ls);
for(const auto &[user, keys] : asKeyValueRange(deviceKeys)) {
QHash<QString, Quotient::DeviceKeys> oldDevices = this->deviceKeys[user];
auto query = database.prepareQuery("SELECT * FROM self_signing_keys WHERE userId=:userId;"_ls);
query.bindValue(":userId"_ls, user);
database->execute(query);
database.execute(query);
auto selfSigningKey = query.next() ? query.value("key"_ls).toString() : QString();
deviceKeys[user].clear();
this->deviceKeys[user].clear();
selfVerifiedDevices[user].clear();
for(const auto &device : keys) {
if(device.userId != user) {
Expand Down Expand Up @@ -580,7 +576,7 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
qCWarning(E2EE) << "failed self signing signature check" << user << device.deviceId;
}
}
deviceKeys[user][device.deviceId] = SLICE(device, DeviceKeys);
this->deviceKeys[user][device.deviceId] = SLICE(device, DeviceKeys);
}
outdatedUsers -= user;
}
Expand All @@ -595,7 +591,7 @@ void ConnectionEncryptionData::handleQueryKeys(const QHash<QString, QHash<QStrin
[this](const event_ptr_tt<EncryptedEvent>& pendingEvent) {
if (!isKnownCurveKey(
pendingEvent->fullJson()[SenderKey].toString(),
pendingEvent->contentPart<QString>(SenderKeyKeyL)))
pendingEvent->contentPart<QString>(SenderKey)))
return false;
handleEncryptedToDeviceEvent(*pendingEvent);
return true;
Expand Down Expand Up @@ -951,3 +947,45 @@ ConnectionEncryptionData::ConnectionEncryptionData(Connection* connection,
QObject::connect(&olmAccount, &QOlmAccount::needsSave, q,
[this] { saveOlmAccount(); });
}

void ConnectionEncryptionData::reloadDevices()
{
outdatedUsers = trackedUsers;
loadOutdatedUserDevices();
}

bool ConnectionEncryptionData::hasConflictingDeviceIdsAndCrossSigningKeys(const QString& userId)
{
auto devices = q->devicesForUser(userId);

auto selfQuery = database.prepareQuery("SELECT key FROM self_signing_keys WHERE userId=:userId;"_ls);
selfQuery.bindValue(":userId"_ls, userId);
database.execute(selfQuery);
if (!selfQuery.next()) {
return false;
}
if (devices.contains(selfQuery.value("key"_ls).toString())) {
return true;
}

auto masterQuery = database.prepareQuery("SELECT key FROM master_keys WHERE userId=:userId;"_ls);
masterQuery.bindValue(":userId"_ls, userId);
database.execute(masterQuery);
if (!masterQuery.next()) {
return false;
}
if (devices.contains(masterQuery.value("key"_ls).toString())) {
return true;
}

auto userQuery = database.prepareQuery("SELECT key FROM user_signing_keys WHERE userId=:userId;"_ls);
userQuery.bindValue(":userId"_ls, userId);
database.execute(userQuery);
if (!userQuery.next()) {
return false;
}
if (devices.contains(userQuery.value("key"_ls).toString())) {
return true;
}
return false;
}
5 changes: 5 additions & 0 deletions Quotient/connectionencryptiondata_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "e2ee/qolmaccount.h"
#include "e2ee/qolmsession.h"

#include "events/encryptedevent.h"

namespace Quotient {

struct DevicesList;
Expand Down Expand Up @@ -36,6 +38,7 @@ namespace _impl {
std::vector<std::unique_ptr<EncryptedEvent>> pendingEncryptedEvents{};
bool isUploadingKeys = false;
bool firstSync = true;
QHash<QString, QHash<QString, bool>> selfVerifiedDevices;

void saveDevicesList();
void loadDevicesList();
Expand Down Expand Up @@ -63,6 +66,7 @@ namespace _impl {
qCDebug(E2EE) << "Saving olm account";
database.storeOlmAccount(olmAccount);
}
void reloadDevices();

std::pair<QByteArray, QByteArray> sessionDecryptMessage(
const QJsonObject& personalCipherObject,
Expand Down Expand Up @@ -97,6 +101,7 @@ namespace _impl {
// get an instance from setup() instead
ConnectionEncryptionData(Connection* connection,
PicklingKey&& picklingKey);
bool hasConflictingDeviceIdsAndCrossSigningKeys(const QString& userId);

private:
void consumeDevicesList(const DevicesList &devicesList);
Expand Down
Loading

0 comments on commit f750922

Please sign in to comment.