diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 51 | ||||
-rw-r--r-- | lib/converters.cpp | 13 | ||||
-rw-r--r-- | lib/crypto/e2ee.h | 47 | ||||
-rw-r--r-- | lib/crypto/qolmaccount.cpp | 36 | ||||
-rw-r--r-- | lib/crypto/qolmaccount.h | 8 | ||||
-rw-r--r-- | lib/encryptionmanager.cpp | 12 | ||||
-rw-r--r-- | lib/networkaccessmanager.cpp | 6 |
7 files changed, 142 insertions, 31 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index f96eeb71..704bc1b4 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -108,7 +108,8 @@ public: QVector<GetLoginFlowsJob::LoginFlow> loginFlows; #ifdef Quotient_E2EE_ENABLED - QScopedPointer<EncryptionManager> encryptionManager; + std::unique_ptr<QOlmAccount> olmAccount; + //QScopedPointer<EncryptionManager> encryptionManager; #endif // Quotient_E2EE_ENABLED QPointer<GetWellknownJob> resolverJob = nullptr; @@ -183,6 +184,9 @@ public: EventPtr sessionDecryptMessage(const EncryptedEvent& encryptedEvent) { + qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; + return {}; + /* #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; return {}; @@ -242,6 +246,7 @@ public: return std::move(decryptedEvent); #endif // Quotient_E2EE_ENABLED +*/ } }; @@ -420,8 +425,8 @@ void Connection::Private::loginToServer(LoginArgTs&&... loginArgs) #ifndef Quotient_E2EE_ENABLED qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; #else // Quotient_E2EE_ENABLED - encryptionManager->uploadIdentityKeys(q); - encryptionManager->uploadOneTimeKeys(q); + //encryptionManager->uploadIdentityKeys(q); + //encryptionManager->uploadOneTimeKeys(q); #endif // Quotient_E2EE_ENABLED }); connect(loginJob, &BaseJob::failure, q, [this, loginJob] { @@ -442,11 +447,19 @@ void Connection::Private::completeSetup(const QString& mxId) qCWarning(E2EE) << "End-to-end encryption (E2EE) support is turned off."; #else // Quotient_E2EE_ENABLED AccountSettings accountSettings(data->userId()); - encryptionManager.reset( - new EncryptionManager(accountSettings.encryptionAccountPickle())); + + // init olmAccount + olmAccount = std::make_unique<QOlmAccount>(data->userId(), data->deviceId()); + if (accountSettings.encryptionAccountPickle().isEmpty()) { - accountSettings.setEncryptionAccountPickle( - encryptionManager->olmAccountPickle()); + // create new account and save unpickle data + olmAccount->createNewAccount(); + accountSettings.setEncryptionAccountPickle(std::get<QByteArray>(olmAccount->pickle(Unencrypted{}))); + // TODO handle pickle errors + } else { + // account already existing + auto pickle = accountSettings.encryptionAccountPickle(); + olmAccount->unpickle(pickle, Unencrypted{}); } #endif // Quotient_E2EE_ENABLED emit q->stateChanged(); @@ -608,16 +621,16 @@ void Connection::onSyncSuccess(SyncData&& data, bool fromCache) d->consumeToDeviceEvents(data.takeToDeviceEvents()); #ifdef Quotient_E2EE_ENABLED // handling device_one_time_keys_count - if (!d->encryptionManager) - { - qCDebug(E2EE) << "Encryption manager is not there yet, updating " - "one-time key counts will be skipped"; - return; - } - if (const auto deviceOneTimeKeysCount = data.deviceOneTimeKeysCount(); - !deviceOneTimeKeysCount.isEmpty()) - d->encryptionManager->updateOneTimeKeyCounts(this, - deviceOneTimeKeysCount); + //if (!d->encryptionManager) + //{ + // qCDebug(E2EE) << "Encryption manager is not there yet, updating " + // "one-time key counts will be skipped"; + // return; + //} + //if (const auto deviceOneTimeKeysCount = data.deviceOneTimeKeysCount(); + // !deviceOneTimeKeysCount.isEmpty()) + // d->encryptionManager->updateOneTimeKeyCounts(this, + // deviceOneTimeKeysCount); #endif // Quotient_E2EE_ENABLED } @@ -745,6 +758,7 @@ void Connection::Private::consumePresenceData(Events&& presenceData) void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents) { +/* #ifdef Quotient_E2EE_ENABLED // handling m.room_key to-device encrypted event visitEach(toDeviceEvents, [this](const EncryptedEvent& ee) { @@ -775,6 +789,7 @@ void Connection::Private::consumeToDeviceEvents(Events&& toDeviceEvents) }); }); #endif +*/ } void Connection::stopSync() @@ -1228,7 +1243,7 @@ bool Connection::isLoggedIn() const { return !accessToken().isEmpty(); } #ifdef Quotient_E2EE_ENABLED QOlmAccount *Connection::olmAccount() const { - return d->encryptionManager->account(); + return d->olmAccount.get(); //d->encryptionManager->account(); } #endif // Quotient_E2EE_ENABLED diff --git a/lib/converters.cpp b/lib/converters.cpp index 444ca4f6..e6dcd854 100644 --- a/lib/converters.cpp +++ b/lib/converters.cpp @@ -3,15 +3,26 @@ #include "converters.h" -#include <QtCore/QVariant> +#include <QVariant> +#include "crypto/e2ee.h" QJsonValue Quotient::JsonConverter<QVariant>::dump(const QVariant& v) { + if (v.canConvert<SignedOneTimeKey>()) { + return toJson(v.value<SignedOneTimeKey>()); + } return QJsonValue::fromVariant(v); } QVariant Quotient::JsonConverter<QVariant>::load(const QJsonValue& jv) { + if (jv.isObject()) { + QJsonObject obj = jv.toObject(); + if (obj.contains("key") && obj.contains("signatures")) { + SignedOneTimeKey signedOneTimeKeys; + signedOneTimeKeys.key = obj["key"].toString(); + } + } return jv.toVariant(); } diff --git a/lib/crypto/e2ee.h b/lib/crypto/e2ee.h index 73dd7f65..2d280185 100644 --- a/lib/crypto/e2ee.h +++ b/lib/crypto/e2ee.h @@ -7,10 +7,13 @@ #include <optional> #include <string> +#include "converters.h" #include <variant> #include <QMap> +#include <QHash> #include <QStringList> +#include <QMetaType> #include "util.h" @@ -68,16 +71,56 @@ struct OneTimeKeys }; //! Struct representing the signed one-time keys. -struct SignedOneTimeKey +class SignedOneTimeKey { +public: + SignedOneTimeKey() = default; + SignedOneTimeKey(const SignedOneTimeKey &) = default; + SignedOneTimeKey &operator=(const SignedOneTimeKey &) = default; //! Required. The unpadded Base64-encoded 32-byte Curve25519 public key. QString key; //! Required. Signatures of the key object. //! The signature is calculated using the process described at Signing JSON. - QMap<QString, QMap<QString, QString>> signatures; + QHash<QString, QHash<QString, QString>> signatures; +}; + + +template <> +struct JsonObjectConverter<SignedOneTimeKey> { + static void fillFrom(const QJsonObject& jo, + SignedOneTimeKey& result) + { + fromJson(jo.value("key"_ls), result.key); + fromJson(jo.value("signatures"_ls), result.signatures); + } + + static void dumpTo(QJsonObject &jo, const SignedOneTimeKey &result) + { + addParam<>(jo, QStringLiteral("key"), result.key); + addParam<>(jo, QStringLiteral("signatures"), result.signatures); + } }; bool operator==(const IdentityKeys& lhs, const IdentityKeys& rhs); +template <typename T> +class asKeyValueRange +{ +public: + asKeyValueRange(T &data) + : m_data{data} + { + } + + auto begin() { return m_data.keyValueBegin(); } + + auto end() { return m_data.keyValueEnd(); } + +private: + T &m_data; +}; + } // namespace Quotient + +Q_DECLARE_METATYPE(Quotient::SignedOneTimeKey) diff --git a/lib/crypto/qolmaccount.cpp b/lib/crypto/qolmaccount.cpp index 76b0a263..fb91c906 100644 --- a/lib/crypto/qolmaccount.cpp +++ b/lib/crypto/qolmaccount.cpp @@ -4,6 +4,8 @@ #ifdef Quotient_E2EE_ENABLED #include "qolmaccount.h" +#include "connection.h" +#include "csapi/keys.h" #include "crypto/qolmutils.h" #include <QJsonObject> #include <QJsonDocument> @@ -138,7 +140,7 @@ size_t QOlmAccount::maxNumberOfOneTimeKeys() const return olm_account_max_number_of_one_time_keys(m_account); } -void QOlmAccount::generateOneTimeKeys(size_t numberOfKeys) const +size_t QOlmAccount::generateOneTimeKeys(size_t numberOfKeys) const { const size_t randomLen = olm_account_generate_one_time_keys_random_length(m_account, numberOfKeys); QByteArray randomBuffer = getRandom(randomLen); @@ -147,6 +149,7 @@ void QOlmAccount::generateOneTimeKeys(size_t numberOfKeys) const if (error == olm_error()) { throw lastError(m_account); } + return error; } OneTimeKeys QOlmAccount::oneTimeKeys() const @@ -212,6 +215,37 @@ OlmAccount *Quotient::QOlmAccount::data() return m_account; } +UploadKeysJob *QOlmAccount::createUploadKeyRequest(const OneTimeKeys &oneTimeKeys) +{ + + DeviceKeys deviceKeys; + deviceKeys.userId = m_userId; + deviceKeys.deviceId = m_deviceId; + deviceKeys.algorithms = QStringList {"m.olm.v1.curve25519-aes-sha2", "m.megolm.v1.aes-sha2"}; + + const auto idKeys = identityKeys(); + deviceKeys.keys["curve25519:" + m_deviceId] = idKeys.curve25519; + deviceKeys.keys["ed25519:" + m_deviceId] = idKeys.ed25519; + + const auto sign = signIdentityKeys(); + deviceKeys.signatures[m_userId]["ed25519:" + m_deviceId] = sign; + + if (oneTimeKeys.curve25519().isEmpty()) { + return new UploadKeysJob(deviceKeys); + } + + // Sign & append the one time keys. + auto temp = signOneTimeKeys(oneTimeKeys); + QHash<QString, QVariant> oneTimeKeysSigned; + for (const auto &[keyId, key] : asKeyValueRange(temp)) { + QVariant keyVar; + keyVar.setValue(key); + oneTimeKeysSigned[keyId] = keyVar; + } + + return new UploadKeysJob(deviceKeys, oneTimeKeysSigned); +} + std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createInboundSession(const QOlmMessage &preKeyMessage) { Q_ASSERT(preKeyMessage.type() == QOlmMessage::PreKey); diff --git a/lib/crypto/qolmaccount.h b/lib/crypto/qolmaccount.h index 4398214a..d61c8748 100644 --- a/lib/crypto/qolmaccount.h +++ b/lib/crypto/qolmaccount.h @@ -4,6 +4,7 @@ #pragma once #ifdef Quotient_E2EE_ENABLED +#include "csapi/keys.h" #include "crypto/e2ee.h" #include "crypto/qolmerrors.h" #include "crypto/qolmmessage.h" @@ -15,6 +16,7 @@ struct OlmAccount; namespace Quotient { class QOlmSession; +class Connection; //! An olm account manages all cryptographic keys used on a device. //! \code{.cpp} @@ -55,7 +57,7 @@ public: size_t maxNumberOfOneTimeKeys() const; //! Generates the supplied number of one time keys. - void generateOneTimeKeys(size_t numberOfKeys) const; + size_t generateOneTimeKeys(size_t numberOfKeys) const; //! Gets the OlmAccount's one time keys formatted as JSON. OneTimeKeys oneTimeKeys() const; @@ -68,6 +70,8 @@ public: SignedOneTimeKey signedOneTimeKey(const QByteArray &key, const QString &signature) const; + UploadKeysJob *createUploadKeyRequest(const OneTimeKeys &oneTimeKeys); + //! Remove the one time key used to create the supplied session. [[nodiscard]] std::optional<QOlmError> removeOneTimeKeys(const std::unique_ptr<QOlmSession> &session) const; @@ -90,7 +94,7 @@ public: QOlmAccount(OlmAccount *account); OlmAccount *data(); private: - OlmAccount *m_account = nullptr; + OlmAccount *m_account = nullptr; // owning QString m_userId; QString m_deviceId; }; diff --git a/lib/encryptionmanager.cpp b/lib/encryptionmanager.cpp index 449eb2a3..c8dc6bdd 100644 --- a/lib/encryptionmanager.cpp +++ b/lib/encryptionmanager.cpp @@ -104,7 +104,7 @@ public: { // Try to decrypt message body using one of the known sessions for that // device - bool sessionsPassed = false; + /*bool sessionsPassed = false; // new e2ee TODO: for (auto &senderSession : sessions) { if (senderSession == sessions.last()) { @@ -152,7 +152,7 @@ public: qCDebug(E2EE) << "try to establish new InboundSession with" << senderKey; QOlmMessage preKeyMessage = QOlmMessage(message.toCiphertext(), QOlmMessage::PreKey); // new e2ee TODO: - const auto sessionResult = olmAccount->createInboundSessionFrom(senderKey.toUtf8(), preKeyMessage); + //const auto sessionResult = olmAccount->createInboundSessionFrom(senderKey.toUtf8(), preKeyMessage); if (const auto error = std::get_if<QOlmError>(&sessionResult)) { qCDebug(E2EE) << "Error decrypting pre-key message when trying " @@ -161,7 +161,7 @@ public: return QString(); } - const auto newSession = std::get<std::unique_ptr<QOlmSession>>(sessionResult); + const auto newSession = std::get<std::unique_ptr<QOlmSession>>(olmAccount->createInboundSessionFrom(senderKey.toUtf8(), preKeyMessage)); qCDebug(E2EE) << "Created new Olm session" << newSession->sessionId(); @@ -178,9 +178,9 @@ public: << "Error removing one time keys" << error.value(); } - sessions.insert(senderKey, std::move(newSession)); - return std::get<QString>(decryptedResult); - } + //sessions.insert(senderKey, std::move(newSession)); TODO + //return std::get<QString>(decryptedResult); + }*/ return QString(); } }; diff --git a/lib/networkaccessmanager.cpp b/lib/networkaccessmanager.cpp index 57618329..293538ee 100644 --- a/lib/networkaccessmanager.cpp +++ b/lib/networkaccessmanager.cpp @@ -40,7 +40,11 @@ public: NetworkAccessManager::NetworkAccessManager(QObject* parent) : QNetworkAccessManager(parent), d(std::make_unique<Private>(this)) -{} +{ + connect(this, &QNetworkAccessManager::sslErrors, this, [](QNetworkReply *reply, const QList<QSslError> &errors) { + reply->ignoreSslErrors(); + }); +} QList<QSslError> NetworkAccessManager::ignoredSslErrors() const { |