From 21ae4eca4c06e500ec04a52ad42772bf8e8e9b6f Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Tue, 31 May 2022 18:58:27 +0200 Subject: Tweak QOlmAccount and data structures around This is mainly to plug the definition of a string-to-variant map for one-time keys (see https://spec.matrix.org/v1.2/client-server-api/#key-algorithms) into the CS API generated code (see the "shortcut OneTimeKeys" commit for gtad.yaml); but along with it came considerable streamlining of code in qolmaccount.cpp. Using std::variant to store that map also warranted converters.h to gain support for that type (even wider than toJson() that is already in dev - a non-trivial merge from dev is in order). --- autotests/testolmaccount.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'autotests') diff --git a/autotests/testolmaccount.cpp b/autotests/testolmaccount.cpp index e31ff6d3..c85718dd 100644 --- a/autotests/testolmaccount.cpp +++ b/autotests/testolmaccount.cpp @@ -198,7 +198,7 @@ void TestOlmAccount::uploadIdentityKey() QVERIFY(idKeys.curve25519.size() > 10); - OneTimeKeys unused; + UnsignedOneTimeKeys unused; auto request = olmAccount->createUploadKeyRequest(unused); connect(request, &BaseJob::result, this, [request, conn] { QCOMPARE(request->oneTimeKeyCounts().size(), 0); @@ -221,7 +221,7 @@ void TestOlmAccount::uploadOneTimeKeys() auto oneTimeKeys = olmAccount->oneTimeKeys(); - QHash oneTimeKeysHash; + OneTimeKeys oneTimeKeysHash; const auto curve = oneTimeKeys.curve25519(); for (const auto &[keyId, key] : asKeyValueRange(curve)) { oneTimeKeysHash["curve25519:"+keyId] = key; @@ -247,12 +247,10 @@ void TestOlmAccount::uploadSignedOneTimeKeys() QCOMPARE(nKeys, 5); auto oneTimeKeys = olmAccount->oneTimeKeys(); - QHash oneTimeKeysHash; + OneTimeKeys oneTimeKeysHash; const auto signedKey = olmAccount->signOneTimeKeys(oneTimeKeys); for (const auto &[keyId, key] : asKeyValueRange(signedKey)) { - QVariant var; - var.setValue(key); - oneTimeKeysHash[keyId] = var; + oneTimeKeysHash[keyId] = key; } auto request = new UploadKeysJob(none, oneTimeKeysHash); connect(request, &BaseJob::result, this, [request, nKeys, conn] { @@ -410,11 +408,9 @@ void TestOlmAccount::claimKeys() // The key is the one bob sent. const auto& oneTimeKey = job->oneTimeKeys().value(userId).value(deviceId); - QVERIFY(oneTimeKey.canConvert()); - - const auto varMap = oneTimeKey.toMap(); - QVERIFY(std::any_of(varMap.constKeyValueBegin(), - varMap.constKeyValueEnd(), [](const auto& kv) { + QVERIFY(std::any_of(oneTimeKey.constKeyValueBegin(), + oneTimeKey.constKeyValueEnd(), + [](const auto& kv) { return kv.first.startsWith( SignedCurve25519Key); })); -- cgit v1.2.3 From cd442611b19ec4a438d0847bf09b7bca99b494d3 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Wed, 1 Jun 2022 08:05:21 +0200 Subject: Fix FTBFS after the merge --- autotests/testolmaccount.cpp | 2 +- lib/connection.cpp | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'autotests') diff --git a/autotests/testolmaccount.cpp b/autotests/testolmaccount.cpp index 60f4ab38..4b32393d 100644 --- a/autotests/testolmaccount.cpp +++ b/autotests/testolmaccount.cpp @@ -404,7 +404,7 @@ void TestOlmAccount::claimKeys() claimKeysJob->oneTimeKeys().value(userId).value(deviceId); for (auto it = oneTimeKeys.begin(); it != oneTimeKeys.end(); ++it) { if (it.key().startsWith(SignedCurve25519Key) - && it.value().isObject()) + && std::holds_alternative(it.value())) return; } QFAIL("The claimed one time key is not in /claim response"); diff --git a/lib/connection.cpp b/lib/connection.cpp index 102fb16d..7885718f 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -376,7 +376,7 @@ public: const QByteArray& message) const; bool createOlmSession(const QString& targetUserId, const QString& targetDeviceId, - const QJsonObject& oneTimeKeyObject); + const OneTimeKeys &oneTimeKeyObject); QString curveKeyForUserDevice(const QString& userId, const QString& device) const; QString edKeyForUserDevice(const QString& userId, @@ -2306,7 +2306,7 @@ std::pair Connection::Private::olmEncryptMessage( bool Connection::Private::createOlmSession(const QString& targetUserId, const QString& targetDeviceId, - const QJsonObject& oneTimeKeyObject) + const OneTimeKeys& oneTimeKeyObject) { static QOlmUtility verifier; qDebug(E2EE) << "Creating a new session for" << targetUserId @@ -2316,17 +2316,23 @@ bool Connection::Private::createOlmSession(const QString& targetUserId, << targetDeviceId; return false; } - auto signedOneTimeKey = oneTimeKeyObject.constBegin()->toObject(); + auto* signedOneTimeKey = + std::get_if(&*oneTimeKeyObject.begin()); + if (!signedOneTimeKey) { + qWarning(E2EE) << "No signed one time key for" << targetUserId + << targetDeviceId; + return false; + } // Verify contents of signedOneTimeKey - for that, drop `signatures` and // `unsigned` and then verify the object against the respective signature const auto signature = - signedOneTimeKey.take("signatures"_ls)[targetUserId]["ed25519:"_ls % targetDeviceId] - .toString() + signedOneTimeKey + ->signatures[targetUserId]["ed25519:"_ls % targetDeviceId] .toLatin1(); - signedOneTimeKey.remove("unsigned"_ls); if (!verifier.ed25519Verify( edKeyForUserDevice(targetUserId, targetDeviceId).toLatin1(), - QJsonDocument(signedOneTimeKey).toJson(QJsonDocument::Compact), + QJsonDocument(toJson(SignedOneTimeKey { signedOneTimeKey->key, {} })) + .toJson(QJsonDocument::Compact), signature)) { qWarning(E2EE) << "Failed to verify one-time-key signature for" << targetUserId << targetDeviceId << ". Skipping this device."; @@ -2336,7 +2342,7 @@ bool Connection::Private::createOlmSession(const QString& targetUserId, curveKeyForUserDevice(targetUserId, targetDeviceId); auto session = QOlmSession::createOutboundSession(olmAccount.get(), recipientCurveKey, - signedOneTimeKey["key"].toString()); + signedOneTimeKey->key); if (!session) { qCWarning(E2EE) << "Failed to create olm session for " << recipientCurveKey << session.error(); -- cgit v1.2.3