diff options
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/e2ee.h | 7 | ||||
-rw-r--r-- | lib/crypto/qolmaccount.cpp | 23 | ||||
-rw-r--r-- | lib/crypto/qolmaccount.h | 15 | ||||
-rw-r--r-- | lib/crypto/qolmerrors.cpp (renamed from lib/crypto/errors.cpp) | 16 | ||||
-rw-r--r-- | lib/crypto/qolmerrors.h (renamed from lib/crypto/errors.h) | 4 | ||||
-rw-r--r-- | lib/crypto/qolminboundsession.cpp | 8 | ||||
-rw-r--r-- | lib/crypto/qolminboundsession.h | 8 | ||||
-rw-r--r-- | lib/crypto/qolmmessage.cpp (renamed from lib/crypto/message.cpp) | 14 | ||||
-rw-r--r-- | lib/crypto/qolmmessage.h (renamed from lib/crypto/message.h) | 10 | ||||
-rw-r--r-- | lib/crypto/qolmoutboundsession.cpp | 14 | ||||
-rw-r--r-- | lib/crypto/qolmoutboundsession.h | 12 | ||||
-rw-r--r-- | lib/crypto/qolmsession.cpp | 246 | ||||
-rw-r--r-- | lib/crypto/qolmsession.cpp.back | 29 | ||||
-rw-r--r-- | lib/crypto/qolmsession.h | 92 | ||||
-rw-r--r-- | lib/crypto/qolmsession.h.back | 49 | ||||
-rw-r--r-- | lib/crypto/qolmutils.cpp (renamed from lib/crypto/utils.cpp) | 2 | ||||
-rw-r--r-- | lib/crypto/qolmutils.h (renamed from lib/crypto/utils.h) | 2 | ||||
-rw-r--r-- | lib/crypto/session.cpp | 242 | ||||
-rw-r--r-- | lib/crypto/session.h | 77 |
19 files changed, 440 insertions, 430 deletions
diff --git a/lib/crypto/e2ee.h b/lib/crypto/e2ee.h index 74f876e4..73dd7f65 100644 --- a/lib/crypto/e2ee.h +++ b/lib/crypto/e2ee.h @@ -5,15 +5,17 @@ #pragma once -#include "util.h" #include <optional> #include <string> #include <variant> -#include <QMap> +#include <QMap> #include <QStringList> +#include "util.h" + namespace Quotient { + inline const auto CiphertextKeyL = "ciphertext"_ls; inline const auto SenderKeyKeyL = "sender_key"_ls; inline const auto DeviceIdKeyL = "device_id"_ls; @@ -37,7 +39,6 @@ inline const auto MegolmV1AesSha2AlgoKey = QStringLiteral("m.megolm.v1.aes-sha2"); inline const QStringList SupportedAlgorithms = { OlmV1Curve25519AesSha2AlgoKey, MegolmV1AesSha2AlgoKey }; - struct Unencrypted {}; struct Encrypted { QByteArray key; diff --git a/lib/crypto/qolmaccount.cpp b/lib/crypto/qolmaccount.cpp index 8824e7ef..fc0fc1cf 100644 --- a/lib/crypto/qolmaccount.cpp +++ b/lib/crypto/qolmaccount.cpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED -#include "crypto/qolmaccount.h" -#include "crypto/utils.h" +#include "qolmaccount.h" +#include "crypto/qolmutils.h" #include <QJsonObject> #include <QJsonDocument> #include <QDebug> @@ -31,7 +31,7 @@ bool operator==(const IdentityKeys& lhs, const IdentityKeys& rhs) } // Convert olm error to enum -OlmError lastError(OlmAccount *account) { +QOlmError lastError(OlmAccount *account) { const std::string error_raw = olm_account_last_error(account); return fromString(error_raw); @@ -77,7 +77,7 @@ void QOlmAccount::unpickle(QByteArray &pickled, const PicklingMode &mode) } } -std::variant<QByteArray, OlmError> QOlmAccount::pickle(const PicklingMode &mode) +std::variant<QByteArray, QOlmError> QOlmAccount::pickle(const PicklingMode &mode) { const QByteArray key = toKey(mode); const size_t pickleLength = olm_pickle_account_length(m_account); @@ -118,6 +118,11 @@ QByteArray QOlmAccount::sign(const QByteArray &message) const return signatureBuffer; } +QByteArray QOlmAccount::sign(const QJsonObject &message) const +{ + return sign(QJsonDocument(message).toJson(QJsonDocument::Compact)); +} + QByteArray QOlmAccount::signIdentityKeys() const { const auto keys = identityKeys(); @@ -197,19 +202,19 @@ OlmAccount *Quotient::QOlmAccount::data() return m_account; } -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createInboundSession(const Message &preKeyMessage) +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createInboundSession(const QOlmMessage &preKeyMessage) { - Q_ASSERT(preKeyMessage.type() == Message::PreKey); + Q_ASSERT(preKeyMessage.type() == QOlmMessage::PreKey); return QOlmSession::createInboundSession(this, preKeyMessage); } -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createInboundSessionFrom(const QByteArray &theirIdentityKey, const Message &preKeyMessage) +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createInboundSessionFrom(const QByteArray &theirIdentityKey, const QOlmMessage &preKeyMessage) { - Q_ASSERT(preKeyMessage.type() == Message::PreKey); + Q_ASSERT(preKeyMessage.type() == QOlmMessage::PreKey); return QOlmSession::createInboundSessionFrom(this, theirIdentityKey, preKeyMessage); } -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmAccount::createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey) +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmAccount::createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey) { return QOlmSession::createOutboundSession(this, theirIdentityKey, theirOneTimeKey); } diff --git a/lib/crypto/qolmaccount.h b/lib/crypto/qolmaccount.h index f98d78ba..b33e3768 100644 --- a/lib/crypto/qolmaccount.h +++ b/lib/crypto/qolmaccount.h @@ -5,9 +5,9 @@ #ifdef Quotient_E2EE_ENABLED #include "crypto/e2ee.h" -#include "crypto/errors.h" -#include "crypto/session.h" -#include <olm/olm.h> +#include "crypto/qolmerrors.h" +#include "crypto/qolmmessage.h" +#include "crypto/qolmsession.h" #include <QObject> struct OlmAccount; @@ -38,13 +38,14 @@ public: void unpickle(QByteArray &picked, const PicklingMode &mode); //! Serialises an OlmAccount to encrypted Base64. - std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode); + std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode); //! Returns the account's public identity keys already formatted as JSON IdentityKeys identityKeys() const; //! Returns the signature of the supplied message. QByteArray sign(const QByteArray &message) const; + QByteArray sign(const QJsonObject& message) const; //! Sign identity keys. QByteArray signIdentityKeys() const; @@ -70,17 +71,17 @@ public: //! Creates an inbound session for sending/receiving messages from a received 'prekey' message. //! //! \param message An Olm pre-key message that was encrypted for this account. - std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const Message &preKeyMessage); + std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSession(const QOlmMessage &preKeyMessage); //! Creates an inbound session for sending/receiving messages from a received 'prekey' message. //! //! \param theirIdentityKey - The identity key of an Olm account that //! encrypted this Olm message. - std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSessionFrom(const QByteArray &theirIdentityKey, const Message &preKeyMessage); + std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSessionFrom(const QByteArray &theirIdentityKey, const QOlmMessage &preKeyMessage); //! Creates an outbound session for sending messages to a specific /// identity and one time key. - std::variant<std::unique_ptr<QOlmSession>, OlmError> createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey); + std::variant<std::unique_ptr<QOlmSession>, QOlmError> createOutboundSession(const QByteArray &theirIdentityKey, const QByteArray &theirOneTimeKey); // HACK do not use directly QOlmAccount(OlmAccount *account); diff --git a/lib/crypto/errors.cpp b/lib/crypto/qolmerrors.cpp index 00ff962d..f407383e 100644 --- a/lib/crypto/errors.cpp +++ b/lib/crypto/qolmerrors.cpp @@ -1,21 +1,21 @@ // SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED -#include "crypto/errors.h" +#include "qolmerrors.h" -Quotient::OlmError Quotient::fromString(const std::string &error_raw) { +Quotient::QOlmError Quotient::fromString(const std::string &error_raw) { if (error_raw.compare("BAD_ACCOUNT_KEY")) { - return OlmError::BadAccountKey; + return QOlmError::BadAccountKey; } else if (error_raw.compare("BAD_MESSAGE_KEY_ID")) { - return OlmError::BadMessageKeyId; + return QOlmError::BadMessageKeyId; } else if (error_raw.compare("INVALID_BASE64")) { - return OlmError::InvalidBase64; + return QOlmError::InvalidBase64; } else if (error_raw.compare("NOT_ENOUGH_RANDOM")) { - return OlmError::NotEnoughRandom; + return QOlmError::NotEnoughRandom; } else if (error_raw.compare("OUTPUT_BUFFER_TOO_SMALL")) { - return OlmError::OutputBufferTooSmall; + return QOlmError::OutputBufferTooSmall; } else { - return OlmError::Unknown; + return QOlmError::Unknown; } } #endif diff --git a/lib/crypto/errors.h b/lib/crypto/qolmerrors.h index 09d2a989..400573c6 100644 --- a/lib/crypto/errors.h +++ b/lib/crypto/qolmerrors.h @@ -10,7 +10,7 @@ namespace Quotient { //! All errors that could be caused by an operation regarding Olm //! Errors are named exactly like the ones in libolm. -enum OlmError +enum QOlmError { BadAccountKey, BadMessageFormat, @@ -24,7 +24,7 @@ enum OlmError Unknown, }; -OlmError fromString(const std::string &error_raw); +QOlmError fromString(const std::string &error_raw); } //namespace Quotient diff --git a/lib/crypto/qolminboundsession.cpp b/lib/crypto/qolminboundsession.cpp index 539fdc51..8f5056d8 100644 --- a/lib/crypto/qolminboundsession.cpp +++ b/lib/crypto/qolminboundsession.cpp @@ -8,7 +8,7 @@ #include <cstring> using namespace Quotient; -OlmError lastError(OlmInboundGroupSession *session) { +QOlmError lastError(OlmInboundGroupSession *session) { const std::string error_raw = olm_inbound_group_session_last_error(session); std::cout << error_raw; @@ -75,7 +75,7 @@ QByteArray QOlmInboundGroupSession::pickle(const PicklingMode &mode) const return pickledBuf; } -std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> QOlmInboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode) +std::variant<std::unique_ptr<QOlmInboundGroupSession>, QOlmError> QOlmInboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode) { QByteArray pickledBuf = pickled; const auto groupSession = olm_inbound_group_session(new uint8_t[olm_inbound_group_session_size()]); @@ -90,7 +90,7 @@ std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> QOlmInboundGrou return std::make_unique<QOlmInboundGroupSession>(groupSession); } -std::variant<std::pair<QString, uint32_t>, OlmError> QOlmInboundGroupSession::decrypt(const QByteArray &message) +std::variant<std::pair<QString, uint32_t>, QOlmError> QOlmInboundGroupSession::decrypt(const QByteArray &message) { // This is for capturing the output of olm_group_decrypt uint32_t messageIndex = 0; @@ -122,7 +122,7 @@ std::variant<std::pair<QString, uint32_t>, OlmError> QOlmInboundGroupSession::de return std::make_pair<QString, qint32>(QString(output), messageIndex); } -std::variant<QByteArray, OlmError> QOlmInboundGroupSession::exportSession(uint32_t messageIndex) +std::variant<QByteArray, QOlmError> QOlmInboundGroupSession::exportSession(uint32_t messageIndex) { const auto keyLen = olm_export_inbound_group_session_length(m_groupSession); QByteArray keyBuf(keyLen, '0'); diff --git a/lib/crypto/qolminboundsession.h b/lib/crypto/qolminboundsession.h index a58fbbbc..6af71cbd 100644 --- a/lib/crypto/qolminboundsession.h +++ b/lib/crypto/qolminboundsession.h @@ -10,7 +10,7 @@ #include <variant> #include <memory> #include "olm/olm.h" -#include "crypto/errors.h" +#include "crypto/qolmerrors.h" #include "crypto/e2ee.h" namespace Quotient { @@ -29,12 +29,12 @@ public: QByteArray pickle(const PicklingMode &mode) const; //! Deserialises from encrypted Base64 that was previously obtained by pickling //! an `OlmInboundGroupSession`. - static std::variant<std::unique_ptr<QOlmInboundGroupSession>, OlmError> unpickle(QByteArray &picked, const PicklingMode &mode); + static std::variant<std::unique_ptr<QOlmInboundGroupSession>, QOlmError> unpickle(QByteArray &picked, const PicklingMode &mode); //! Decrypts ciphertext received for this group session. - std::variant<std::pair<QString, uint32_t>, OlmError> decrypt(const QByteArray &message); + std::variant<std::pair<QString, uint32_t>, QOlmError> decrypt(const QByteArray &message); //! Export the base64-encoded ratchet key for this session, at the given index, //! in a format which can be used by import. - std::variant<QByteArray, OlmError> exportSession(uint32_t messageIndex); + std::variant<QByteArray, QOlmError> exportSession(uint32_t messageIndex); //! Get the first message index we know how to decrypt. uint32_t firstKnownIndex() const; //! Get a base64-encoded identifier for this session. diff --git a/lib/crypto/message.cpp b/lib/crypto/qolmmessage.cpp index 830633bf..ae98d52f 100644 --- a/lib/crypto/message.cpp +++ b/lib/crypto/qolmmessage.cpp @@ -3,36 +3,36 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED -#include "crypto/message.h" +#include "qolmmessage.h" using namespace Quotient; -Message::Message(const QByteArray &ciphertext, Message::Type type) +QOlmMessage::QOlmMessage(const QByteArray &ciphertext, QOlmMessage::Type type) : QByteArray(std::move(ciphertext)) , m_messageType(type) { Q_ASSERT_X(!ciphertext.isEmpty(), "olm message", "Ciphertext is empty"); } -Message::Message(const Message &message) +QOlmMessage::QOlmMessage(const QOlmMessage &message) : QByteArray(message) , m_messageType(message.type()) { } -Message::Type Message::type() const +QOlmMessage::Type QOlmMessage::type() const { return m_messageType; } -QByteArray Message::toCiphertext() const +QByteArray QOlmMessage::toCiphertext() const { return QByteArray(*this); } -Message Message::fromCiphertext(const QByteArray &ciphertext) +QOlmMessage QOlmMessage::fromCiphertext(const QByteArray &ciphertext) { - return Message(ciphertext, Message::General); + return QOlmMessage(ciphertext, QOlmMessage::General); } diff --git a/lib/crypto/message.h b/lib/crypto/qolmmessage.h index 1ae19ba8..d203364d 100644 --- a/lib/crypto/message.h +++ b/lib/crypto/qolmmessage.h @@ -18,7 +18,7 @@ namespace Quotient { * * The class provides functions to get a type and the ciphertext. */ -class Message : public QByteArray { +class QOlmMessage : public QByteArray { Q_GADGET public: enum Type { @@ -27,11 +27,11 @@ public: }; Q_ENUM(Type) - Message() = default; - explicit Message(const QByteArray &ciphertext, Type type = General); - explicit Message(const Message &message); + QOlmMessage() = default; + explicit QOlmMessage(const QByteArray &ciphertext, Type type = General); + explicit QOlmMessage(const QOlmMessage &message); - static Message fromCiphertext(const QByteArray &ciphertext); + static QOlmMessage fromCiphertext(const QByteArray &ciphertext); Q_INVOKABLE Type type() const; Q_INVOKABLE QByteArray toCiphertext() const; diff --git a/lib/crypto/qolmoutboundsession.cpp b/lib/crypto/qolmoutboundsession.cpp index 3bfb0187..14b7368e 100644 --- a/lib/crypto/qolmoutboundsession.cpp +++ b/lib/crypto/qolmoutboundsession.cpp @@ -3,12 +3,12 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED -#include "crypto/qolmoutboundsession.h" -#include "crypto/utils.h" +#include "qolmoutboundsession.h" +#include "crypto/qolmutils.h" using namespace Quotient; -OlmError lastError(OlmOutboundGroupSession *session) { +QOlmError lastError(OlmOutboundGroupSession *session) { const std::string error_raw = olm_outbound_group_session_last_error(session); return fromString(error_raw); @@ -48,7 +48,7 @@ std::unique_ptr<QOlmOutboundGroupSession> QOlmOutboundGroupSession::create() return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession); } -std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::pickle(const PicklingMode &mode) +std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::pickle(const PicklingMode &mode) { QByteArray pickledBuf(olm_pickle_outbound_group_session_length(m_groupSession), '0'); QByteArray key = toKey(mode); @@ -65,7 +65,7 @@ std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::pickle(const Pickli } -std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> QOlmOutboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode) +std::variant<std::unique_ptr<QOlmOutboundGroupSession>, QOlmError> QOlmOutboundGroupSession::unpickle(QByteArray &pickled, const PicklingMode &mode) { QByteArray pickledBuf = pickled; auto *olmOutboundGroupSession = olm_outbound_group_session(new uint8_t[olm_outbound_group_session_size()]); @@ -84,7 +84,7 @@ std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> QOlmOutboundGr return std::make_unique<QOlmOutboundGroupSession>(olmOutboundGroupSession); } -std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::encrypt(const QString &plaintext) +std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::encrypt(const QString &plaintext) { QByteArray plaintextBuf = plaintext.toUtf8(); const auto messageMaxLen = olm_group_encrypt_message_length(m_groupSession, plaintextBuf.length()); @@ -116,7 +116,7 @@ QByteArray QOlmOutboundGroupSession::sessionId() const return idBuffer; } -std::variant<QByteArray, OlmError> QOlmOutboundGroupSession::sessionKey() const +std::variant<QByteArray, QOlmError> QOlmOutboundGroupSession::sessionKey() const { const auto keyMaxLength = olm_outbound_group_session_key_length(m_groupSession); QByteArray keyBuffer(keyMaxLength, '0'); diff --git a/lib/crypto/qolmoutboundsession.h b/lib/crypto/qolmoutboundsession.h index 6c6c635c..6b4fd30b 100644 --- a/lib/crypto/qolmoutboundsession.h +++ b/lib/crypto/qolmoutboundsession.h @@ -4,8 +4,8 @@ #pragma once #ifdef Quotient_E2EE_ENABLED -#include "olm/olm.h" // from Olm -#include "crypto/errors.h" +#include "olm/olm.h" +#include "crypto/qolmerrors.h" #include "crypto/e2ee.h" #include <memory> @@ -22,12 +22,12 @@ public: //! Throw OlmError on errors static std::unique_ptr<QOlmOutboundGroupSession> create(); //! Serialises an `QOlmOutboundGroupSession` to encrypted Base64. - std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode); + std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode); //! Deserialises from encrypted Base64 that was previously obtained by //! pickling a `QOlmOutboundGroupSession`. - static std::variant<std::unique_ptr<QOlmOutboundGroupSession>, OlmError> unpickle(QByteArray &pickled, const PicklingMode &mode); + static std::variant<std::unique_ptr<QOlmOutboundGroupSession>, QOlmError> unpickle(QByteArray &pickled, const PicklingMode &mode); //! Encrypts a plaintext message using the session. - std::variant<QByteArray, OlmError> encrypt(const QString &plaintext); + std::variant<QByteArray, QOlmError> encrypt(const QString &plaintext); //! Get the current message index for this session. //! @@ -42,7 +42,7 @@ public: //! //! Each message is sent with a different ratchet key. This function returns the //! ratchet key that will be used for the next message. - std::variant<QByteArray, OlmError> sessionKey() const; + std::variant<QByteArray, QOlmError> sessionKey() const; QOlmOutboundGroupSession(OlmOutboundGroupSession *groupSession); private: OlmOutboundGroupSession *m_groupSession; diff --git a/lib/crypto/qolmsession.cpp b/lib/crypto/qolmsession.cpp index afa42728..cfe21650 100644 --- a/lib/crypto/qolmsession.cpp +++ b/lib/crypto/qolmsession.cpp @@ -1,29 +1,243 @@ -// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> +// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru> // // SPDX-License-Identifier: LGPL-2.1-or-later -#include "crypto/qolmsession.h" +#ifdef Quotient_E2EE_ENABLED +#include "qolmsession.h" +#include "crypto/qolmutils.h" +#include "logging.h" +#include <cstring> +#include <QDebug> using namespace Quotient; -std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext) +QOlmError lastError(OlmSession* session) { + const std::string error_raw = olm_session_last_error(session); + + return fromString(error_raw); +} + +Quotient::QOlmSession::~QOlmSession() +{ + olm_clear_session(m_session); + delete[](reinterpret_cast<uint8_t *>(m_session)); +} + +OlmSession* QOlmSession::create() { - if (messageType == OLM_MESSAGE_TYPE_PRE_KEY) { - return PreKeyMessage { ciphertext }; - } else if (messageType == OLM_MESSAGE_TYPE_MESSAGE) { - return Message { ciphertext }; + return olm_session(new uint8_t[olm_session_size()]); +} + +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInbound(QOlmAccount *account, const QOlmMessage &preKeyMessage, bool from, const QString &theirIdentityKey) +{ + if (preKeyMessage.type() != QOlmMessage::PreKey) { + qCDebug(E2EE) << "The message is not a pre-key"; + throw BadMessageFormat; } - return std::nullopt; + + const auto olmSession = create(); + + QByteArray oneTimeKeyMessageBuf = preKeyMessage.toCiphertext(); + QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8(); + size_t error = 0; + if (from) { + error = olm_create_inbound_session_from(olmSession, account->data(), theirIdentityKeyBuf.data(), theirIdentityKeyBuf.length(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length()); + } else { + error = olm_create_inbound_session(olmSession, account->data(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length()); + } + + if (error == olm_error()) { + const auto lastErr = lastError(olmSession); + if (lastErr == QOlmError::NotEnoughRandom) { + throw lastErr; + } + return lastErr; + } + + return std::make_unique<QOlmSession>(olmSession); } -std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message) +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInboundSession(QOlmAccount *account, const QOlmMessage &preKeyMessage) { - return std::visit([](auto &arg) { - using T = std::decay_t<decltype(arg)>; - if constexpr (std::is_same_v<T, Message>) { - return std::make_pair<OlmMessageType, QByteArray>(MessageType, QByteArray(arg.message)); - } else if constexpr (std::is_same_v<T, PreKeyMessage>) { - return std::make_pair<OlmMessageType, QByteArray>(PreKeyType, QByteArray(arg.message)); + return createInbound(account, preKeyMessage); +} + +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const QOlmMessage &preKeyMessage) +{ + return createInbound(account, preKeyMessage, true, theirIdentityKey); +} + +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey) +{ + auto *olmOutboundSession = create(); + const auto randomLen = olm_create_outbound_session_random_length(olmOutboundSession); + QByteArray randomBuf = getRandom(randomLen); + + QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8(); + QByteArray theirOneTimeKeyBuf = theirOneTimeKey.toUtf8(); + const auto error = olm_create_outbound_session(olmOutboundSession, + account->data(), + reinterpret_cast<uint8_t *>(theirIdentityKeyBuf.data()), theirIdentityKeyBuf.length(), + reinterpret_cast<uint8_t *>(theirOneTimeKeyBuf.data()), theirOneTimeKeyBuf.length(), + reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length()); + + if (error == olm_error()) { + const auto lastErr = lastError(olmOutboundSession); + if (lastErr == QOlmError::NotEnoughRandom) { + throw lastErr; } - }, message); + return lastErr; + } + + randomBuf.clear(); + return std::make_unique<QOlmSession>(olmOutboundSession); +} + +std::variant<QByteArray, QOlmError> QOlmSession::pickle(const PicklingMode &mode) +{ + QByteArray pickledBuf(olm_pickle_session_length(m_session), '0'); + QByteArray key = toKey(mode); + const auto error = olm_pickle_session(m_session, key.data(), key.length(), + pickledBuf.data(), pickledBuf.length()); + + if (error == olm_error()) { + return lastError(m_session); + } + + key.clear(); + + return pickledBuf; +} + +std::variant<std::unique_ptr<QOlmSession>, QOlmError> QOlmSession::unpickle(const QByteArray &pickled, const PicklingMode &mode) +{ + QByteArray pickledBuf = pickled; + auto *olmSession = create(); + QByteArray key = toKey(mode); + const auto error = olm_unpickle_session(olmSession, key.data(), key.length(), + pickledBuf.data(), pickledBuf.length()); + if (error == olm_error()) { + return lastError(olmSession); + } + + key.clear(); + return std::make_unique<QOlmSession>(olmSession); } + +QOlmMessage QOlmSession::encrypt(const QString &plaintext) +{ + QByteArray plaintextBuf = plaintext.toUtf8(); + const auto messageMaxLen = olm_encrypt_message_length(m_session, plaintextBuf.length()); + QByteArray messageBuf(messageMaxLen, '0'); + const auto messageType = encryptMessageType(); + const auto randomLen = olm_encrypt_random_length(m_session); + QByteArray randomBuf = getRandom(randomLen); + const auto error = olm_encrypt(m_session, + reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextBuf.length(), + reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length(), + reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length()); + + if (error == olm_error()) { + throw lastError(m_session); + } + + return QOlmMessage(messageBuf, messageType); +} + +std::variant<QString, QOlmError> QOlmSession::decrypt(const QOlmMessage &message) const +{ + const auto messageType = message.type(); + const auto ciphertext = message.toCiphertext(); + const auto messageTypeValue = messageType == QOlmMessage::Type::General + ? OLM_MESSAGE_TYPE_MESSAGE : OLM_MESSAGE_TYPE_PRE_KEY; + + // We need to clone the message because + // olm_decrypt_max_plaintext_length destroys the input buffer + QByteArray messageBuf(ciphertext.length(), '0'); + std::copy(message.begin(), message.end(), messageBuf.begin()); + + const auto plaintextMaxLen = olm_decrypt_max_plaintext_length(m_session, messageTypeValue, + reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length()); + + if (plaintextMaxLen == olm_error()) { + return lastError(m_session); + } + + QByteArray plaintextBuf(plaintextMaxLen, '0'); + QByteArray messageBuf2(ciphertext.length(), '0'); + std::copy(message.begin(), message.end(), messageBuf2.begin()); + + const auto plaintextResultLen = olm_decrypt(m_session, messageTypeValue, + reinterpret_cast<uint8_t *>(messageBuf2.data()), messageBuf2.length(), + reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextMaxLen); + + if (plaintextResultLen == olm_error()) { + const auto lastErr = lastError(m_session); + if (lastErr == QOlmError::OutputBufferTooSmall) { + throw lastErr; + } + return lastErr; + } + QByteArray output(plaintextResultLen, '0'); + std::memcpy(output.data(), plaintextBuf.data(), plaintextResultLen); + plaintextBuf.clear(); + return output; +} + +QOlmMessage::Type QOlmSession::encryptMessageType() +{ + const auto messageTypeResult = olm_encrypt_message_type(m_session); + if (messageTypeResult == olm_error()) { + throw lastError(m_session); + } + if (messageTypeResult == OLM_MESSAGE_TYPE_PRE_KEY) { + return QOlmMessage::PreKey; + } + return QOlmMessage::General; +} + +QByteArray QOlmSession::sessionId() const +{ + const auto idMaxLength = olm_session_id_length(m_session); + QByteArray idBuffer(idMaxLength, '0'); + const auto error = olm_session_id(m_session, reinterpret_cast<uint8_t *>(idBuffer.data()), + idBuffer.length()); + if (error == olm_error()) { + throw lastError(m_session); + } + return idBuffer; +} + +bool QOlmSession::hasReceivedMessage() const +{ + return olm_session_has_received_message(m_session); +} + +std::variant<bool, QOlmError> QOlmSession::matchesInboundSession(QOlmMessage &preKeyMessage) +{ + Q_ASSERT(preKeyMessage.type() == QOlmMessage::Type::PreKey); + QByteArray oneTimeKeyBuf(preKeyMessage.data()); + const auto matchesResult = olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(), oneTimeKeyBuf.length()); + + if (matchesResult == olm_error()) { + return lastError(m_session); + } + switch (matchesResult) { + case 0: + return false; + case 1: + return true; + default: + return QOlmError::Unknown; + } +} + +QOlmSession::QOlmSession(OlmSession *session) + : m_session(session) +{ +} + +#endif // Quotient_E2EE_ENABLED + + + diff --git a/lib/crypto/qolmsession.cpp.back b/lib/crypto/qolmsession.cpp.back new file mode 100644 index 00000000..ee8b2a7f --- /dev/null +++ b/lib/crypto/qolmsession.cpp.back @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#include "olm/qolmsession.h" + +using namespace Quotient; + +std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext) +{ + if (messageType == OLM_MESSAGE_TYPE_PRE_KEY) { + return PreKeyMessage { ciphertext }; + } else if (messageType == OLM_MESSAGE_TYPE_MESSAGE) { + return QOlmMessage { ciphertext }; + } + return std::nullopt; +} + +std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message) +{ + return std::visit([](auto &arg) { + using T = std::decay_t<decltype(arg)>; + if constexpr (std::is_same_v<T, QOlmMessage>) { + return std::make_pair<OlmMessageType, QByteArray>(MessageType, QByteArray(arg.message)); + } else if constexpr (std::is_same_v<T, PreKeyMessage>) { + return std::make_pair<OlmMessageType, QByteArray>(PreKeyType, QByteArray(arg.message)); + } + }, message); +} diff --git a/lib/crypto/qolmsession.h b/lib/crypto/qolmsession.h index 3be3c7fc..6e13801e 100644 --- a/lib/crypto/qolmsession.h +++ b/lib/crypto/qolmsession.h @@ -1,49 +1,77 @@ -// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> +// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru> // // SPDX-License-Identifier: LGPL-2.1-or-later #pragma once -#include <variant> -#include <olm/olm.h> +#ifdef Quotient_E2EE_ENABLED + +#include <QDebug> +#include <olm/olm.h> // FIXME: OlmSession #include "crypto/e2ee.h" -#include "crypto/errors.h" +#include "crypto/qolmmessage.h" +#include "crypto/qolmerrors.h" +#include "crypto/qolmaccount.h" namespace Quotient { -//! An encrypted Olm message. -struct Message { - QByteArray message; -}; +class QOlmAccount; +class QOlmSession; -//! A encrypted Olm pre-key message. -//! -//! This message, unlike a normal Message, can be used to create new Olm sessions. -struct PreKeyMessage -{ - QByteArray message; -}; -enum OlmMessageType +//! Either an outbound or inbound session for secure communication. +class QOlmSession { - PreKeyType, - MessageType, -}; +public: + ~QOlmSession(); + //! Creates an inbound session for sending/receiving messages from a received 'prekey' message. + static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSession(QOlmAccount *account, const QOlmMessage &preKeyMessage); + static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const QOlmMessage &preKeyMessage); + static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey); + //! Serialises an `QOlmSession` to encrypted Base64. + std::variant<QByteArray, QOlmError> pickle(const PicklingMode &mode); + //! Deserialises from encrypted Base64 that was previously obtained by pickling a `QOlmSession`. + static std::variant<std::unique_ptr<QOlmSession>, QOlmError> unpickle(const QByteArray &pickled, const PicklingMode &mode); + //! Encrypts a plaintext message using the session. + QOlmMessage encrypt(const QString &plaintext); -using OlmMessage = std::variant<Message, PreKeyMessage>; + //! Decrypts a message using this session. Decoding is lossy, meaing if + //! the decrypted plaintext contains invalid UTF-8 symbols, they will + //! be returned as `U+FFFD` (�). + std::variant<QString, QOlmError> decrypt(const QOlmMessage &message) const; -std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext); + //! Get a base64-encoded identifier for this session. + QByteArray sessionId() const; -std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message); + //! The type of the next message that will be returned from encryption. + QOlmMessage::Type encryptMessageType(); -//class QOlmSession -//{ -// /// Creates an inbound session for sending/receiving messages from a received 'prekey' message. -// static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const QOlmAccount &account, -// PreKeyMessage &message); -// -////private: -// //static std::variant<std::unique_ptr<QOlmSession>, OlmError> createSessionWith(std::function<std::variant<size_t(OlmSession *)>> func); -//} + //! Checker for any received messages for this session. + bool hasReceivedMessage() const; + + //! Checks if the 'prekey' message is for this in-bound session. + std::variant<bool, QOlmError> matchesInboundSession(QOlmMessage &preKeyMessage); + + friend bool operator<(const QOlmSession& lhs, const QOlmSession& rhs) + { + return lhs.sessionId() < rhs.sessionId(); + } + + friend bool operator<(const std::unique_ptr<QOlmSession> &lhs, const std::unique_ptr<QOlmSession> &rhs) { + return *lhs < *rhs; + } + + QOlmSession(OlmSession* session); +private: + //! Helper function for creating new sessions and handling errors. + static OlmSession* create(); + static std::variant<std::unique_ptr<QOlmSession>, QOlmError> createInbound(QOlmAccount *account, const QOlmMessage& preKeyMessage, bool from = false, const QString& theirIdentityKey = ""); + OlmSession* m_session; +}; + + +//using QOlmSessionPtr = std::unique_ptr<QOlmSession>; + +} //namespace Quotient -} +#endif // Quotient_E2EE_ENABLED diff --git a/lib/crypto/qolmsession.h.back b/lib/crypto/qolmsession.h.back new file mode 100644 index 00000000..cbba5cef --- /dev/null +++ b/lib/crypto/qolmsession.h.back @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org> +// +// SPDX-License-Identifier: LGPL-2.1-or-later + +#pragma once + +#include "olm/e2ee.h" +#include "olm/olm.h" +#include "olm/errors.h" +#include <variant> + +namespace Quotient { + +//! An encrypted Olm message. +struct QOlmMessage { + QByteArray message; +}; + +//! A encrypted Olm pre-key message. +//! +//! This message, unlike a normal Message, can be used to create new Olm sessions. +struct PreKeyMessage +{ + QByteArray message; +}; + +enum OlmMessageType +{ + PreKeyType, + MessageType, +}; + +using OlmMessage = std::variant<QOlmMessage, PreKeyMessage>; + +std::optional<OlmMessage> fromTypeAndCipthertext(size_t messageType, const QByteArray &ciphertext); + +std::pair<OlmMessageType, QByteArray> toPair(const OlmMessage &message); + +//class QOlmSession +//{ +// /// Creates an inbound session for sending/receiving messages from a received 'prekey' message. +// static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(const QOlmAccount &account, +// PreKeyMessage &message); +// +////private: +// //static std::variant<std::unique_ptr<QOlmSession>, OlmError> createSessionWith(std::function<std::variant<size_t(OlmSession *)>> func); +//} + +} diff --git a/lib/crypto/utils.cpp b/lib/crypto/qolmutils.cpp index cb20abf8..a486ea0f 100644 --- a/lib/crypto/utils.cpp +++ b/lib/crypto/qolmutils.cpp @@ -3,7 +3,7 @@ // SPDX-License-Identifier: LGPL-2.1-or-later #ifdef Quotient_E2EE_ENABLED -#include "crypto/utils.h" +#include "crypto/qolmutils.h" #include <QDebug> #include <openssl/rand.h> diff --git a/lib/crypto/utils.h b/lib/crypto/qolmutils.h index cea87144..11e9f3cc 100644 --- a/lib/crypto/utils.h +++ b/lib/crypto/qolmutils.h @@ -5,6 +5,8 @@ #pragma once #ifdef Quotient_E2EE_ENABLED +#include <QByteArray> + #include "crypto/e2ee.h" namespace Quotient { diff --git a/lib/crypto/session.cpp b/lib/crypto/session.cpp deleted file mode 100644 index 8b2cb022..00000000 --- a/lib/crypto/session.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru> -// -// SPDX-License-Identifier: LGPL-2.1-or-later - -#ifdef Quotient_E2EE_ENABLED -#include "crypto/session.h" -#include "crypto/utils.h" -#include "logging.h" -#include <cstring> - -using namespace Quotient; - -OlmError lastError(OlmSession* session) { - const std::string error_raw = olm_session_last_error(session); - - return fromString(error_raw); -} - -Quotient::QOlmSession::~QOlmSession() -{ - olm_clear_session(m_session); - delete[](reinterpret_cast<uint8_t *>(m_session)); -} - -OlmSession* QOlmSession::create() -{ - return olm_session(new uint8_t[olm_session_size()]); -} - -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInbound(QOlmAccount *account, const Message &preKeyMessage, bool from, const QString &theirIdentityKey) -{ - if (preKeyMessage.type() != Message::PreKey) { - qCDebug(E2EE) << "The message is not a pre-key"; - throw BadMessageFormat; - } - - const auto olmSession = create(); - - QByteArray oneTimeKeyMessageBuf = preKeyMessage.toCiphertext(); - QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8(); - size_t error = 0; - if (from) { - error = olm_create_inbound_session_from(olmSession, account->data(), theirIdentityKeyBuf.data(), theirIdentityKeyBuf.length(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length()); - } else { - error = olm_create_inbound_session(olmSession, account->data(), oneTimeKeyMessageBuf.data(), oneTimeKeyMessageBuf.length()); - } - - if (error == olm_error()) { - const auto lastErr = lastError(olmSession); - if (lastErr == OlmError::NotEnoughRandom) { - throw lastErr; - } - return lastErr; - } - - return std::make_unique<QOlmSession>(olmSession); -} - -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInboundSession(QOlmAccount *account, const Message &preKeyMessage) -{ - return createInbound(account, preKeyMessage); -} - -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const Message &preKeyMessage) -{ - return createInbound(account, preKeyMessage, true, theirIdentityKey); -} - -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey) -{ - auto *olmOutboundSession = create(); - const auto randomLen = olm_create_outbound_session_random_length(olmOutboundSession); - QByteArray randomBuf = getRandom(randomLen); - - QByteArray theirIdentityKeyBuf = theirIdentityKey.toUtf8(); - QByteArray theirOneTimeKeyBuf = theirOneTimeKey.toUtf8(); - const auto error = olm_create_outbound_session(olmOutboundSession, - account->data(), - reinterpret_cast<uint8_t *>(theirIdentityKeyBuf.data()), theirIdentityKeyBuf.length(), - reinterpret_cast<uint8_t *>(theirOneTimeKeyBuf.data()), theirOneTimeKeyBuf.length(), - reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length()); - - if (error == olm_error()) { - const auto lastErr = lastError(olmOutboundSession); - if (lastErr == OlmError::NotEnoughRandom) { - throw lastErr; - } - return lastErr; - } - - randomBuf.clear(); - return std::make_unique<QOlmSession>(olmOutboundSession); -} - -std::variant<QByteArray, OlmError> QOlmSession::pickle(const PicklingMode &mode) -{ - QByteArray pickledBuf(olm_pickle_session_length(m_session), '0'); - QByteArray key = toKey(mode); - const auto error = olm_pickle_session(m_session, key.data(), key.length(), - pickledBuf.data(), pickledBuf.length()); - - if (error == olm_error()) { - return lastError(m_session); - } - - key.clear(); - - return pickledBuf; -} - -std::variant<std::unique_ptr<QOlmSession>, OlmError> QOlmSession::unpickle(const QByteArray &pickled, const PicklingMode &mode) -{ - QByteArray pickledBuf = pickled; - auto *olmSession = create(); - QByteArray key = toKey(mode); - const auto error = olm_unpickle_session(olmSession, key.data(), key.length(), - pickledBuf.data(), pickledBuf.length()); - if (error == olm_error()) { - return lastError(olmSession); - } - - key.clear(); - return std::make_unique<QOlmSession>(olmSession); -} - -Message QOlmSession::encrypt(const QString &plaintext) -{ - QByteArray plaintextBuf = plaintext.toUtf8(); - const auto messageMaxLen = olm_encrypt_message_length(m_session, plaintextBuf.length()); - QByteArray messageBuf(messageMaxLen, '0'); - const auto messageType = encryptMessageType(); - const auto randomLen = olm_encrypt_random_length(m_session); - QByteArray randomBuf = getRandom(randomLen); - const auto error = olm_encrypt(m_session, - reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextBuf.length(), - reinterpret_cast<uint8_t *>(randomBuf.data()), randomBuf.length(), - reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length()); - - if (error == olm_error()) { - throw lastError(m_session); - } - - return Message(messageBuf, messageType); -} - -std::variant<QString, OlmError> QOlmSession::decrypt(const Message &message) const -{ - const auto messageType = message.type(); - const auto ciphertext = message.toCiphertext(); - const auto messageTypeValue = messageType == Message::Type::General - ? OLM_MESSAGE_TYPE_MESSAGE : OLM_MESSAGE_TYPE_PRE_KEY; - - // We need to clone the message because - // olm_decrypt_max_plaintext_length destroys the input buffer - QByteArray messageBuf(ciphertext.length(), '0'); - std::copy(message.begin(), message.end(), messageBuf.begin()); - - const auto plaintextMaxLen = olm_decrypt_max_plaintext_length(m_session, messageTypeValue, - reinterpret_cast<uint8_t *>(messageBuf.data()), messageBuf.length()); - - if (plaintextMaxLen == olm_error()) { - return lastError(m_session); - } - - QByteArray plaintextBuf(plaintextMaxLen, '0'); - QByteArray messageBuf2(ciphertext.length(), '0'); - std::copy(message.begin(), message.end(), messageBuf2.begin()); - - const auto plaintextResultLen = olm_decrypt(m_session, messageTypeValue, - reinterpret_cast<uint8_t *>(messageBuf2.data()), messageBuf2.length(), - reinterpret_cast<uint8_t *>(plaintextBuf.data()), plaintextMaxLen); - - if (plaintextResultLen == olm_error()) { - const auto lastErr = lastError(m_session); - if (lastErr == OlmError::OutputBufferTooSmall) { - throw lastErr; - } - return lastErr; - } - QByteArray output(plaintextResultLen, '0'); - std::memcpy(output.data(), plaintextBuf.data(), plaintextResultLen); - plaintextBuf.clear(); - return output; -} - -Message::Type QOlmSession::encryptMessageType() -{ - const auto messageTypeResult = olm_encrypt_message_type(m_session); - if (messageTypeResult == olm_error()) { - throw lastError(m_session); - } - if (messageTypeResult == OLM_MESSAGE_TYPE_PRE_KEY) { - return Message::PreKey; - } - return Message::General; -} - -QByteArray QOlmSession::sessionId() const -{ - const auto idMaxLength = olm_session_id_length(m_session); - QByteArray idBuffer(idMaxLength, '0'); - const auto error = olm_session_id(m_session, reinterpret_cast<uint8_t *>(idBuffer.data()), - idBuffer.length()); - if (error == olm_error()) { - throw lastError(m_session); - } - return idBuffer; -} - -bool QOlmSession::hasReceivedMessage() const -{ - return olm_session_has_received_message(m_session); -} - -std::variant<bool, OlmError> QOlmSession::matchesInboundSession(Message &preKeyMessage) -{ - Q_ASSERT(preKeyMessage.type() == Message::Type::PreKey); - QByteArray oneTimeKeyBuf(preKeyMessage.data()); - const auto matchesResult = olm_matches_inbound_session(m_session, oneTimeKeyBuf.data(), oneTimeKeyBuf.length()); - - if (matchesResult == olm_error()) { - return lastError(m_session); - } - switch (matchesResult) { - case 0: - return false; - case 1: - return true; - default: - return OlmError::Unknown; - } -} - -QOlmSession::QOlmSession(OlmSession *session) - : m_session(session) -{ -} - -#endif // Quotient_E2EE_ENABLED - - - diff --git a/lib/crypto/session.h b/lib/crypto/session.h deleted file mode 100644 index 24702564..00000000 --- a/lib/crypto/session.h +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-FileCopyrightText: 2021 Alexey Andreyev <aa13q@ya.ru> -// -// SPDX-License-Identifier: LGPL-2.1-or-later - -#pragma once - -#ifdef Quotient_E2EE_ENABLED - -#include <QDebug> -#include <olm/olm.h> -#include "crypto/e2ee.h" -#include "crypto/message.h" -#include "crypto/errors.h" -#include "crypto/qolmaccount.h" - -namespace Quotient { - -class QOlmAccount; -class QOlmSession; - - -//! Either an outbound or inbound session for secure communication. -class QOlmSession -{ -public: - ~QOlmSession(); - //! Creates an inbound session for sending/receiving messages from a received 'prekey' message. - static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSession(QOlmAccount *account, const Message &preKeyMessage); - static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInboundSessionFrom(QOlmAccount *account, const QString &theirIdentityKey, const Message &preKeyMessage); - static std::variant<std::unique_ptr<QOlmSession>, OlmError> createOutboundSession(QOlmAccount *account, const QString &theirIdentityKey, const QString &theirOneTimeKey); - //! Serialises an `QOlmSession` to encrypted Base64. - std::variant<QByteArray, OlmError> pickle(const PicklingMode &mode); - //! Deserialises from encrypted Base64 that was previously obtained by pickling a `QOlmSession`. - static std::variant<std::unique_ptr<QOlmSession>, OlmError> unpickle(const QByteArray &pickled, const PicklingMode &mode); - //! Encrypts a plaintext message using the session. - Message encrypt(const QString &plaintext); - - //! Decrypts a message using this session. Decoding is lossy, meaing if - //! the decrypted plaintext contains invalid UTF-8 symbols, they will - //! be returned as `U+FFFD` (�). - std::variant<QString, OlmError> decrypt(const Message &message) const; - - //! Get a base64-encoded identifier for this session. - QByteArray sessionId() const; - - //! The type of the next message that will be returned from encryption. - Message::Type encryptMessageType(); - - //! Checker for any received messages for this session. - bool hasReceivedMessage() const; - - //! Checks if the 'prekey' message is for this in-bound session. - std::variant<bool, OlmError> matchesInboundSession(Message &preKeyMessage); - - friend bool operator<(const QOlmSession& lhs, const QOlmSession& rhs) - { - return lhs.sessionId() < rhs.sessionId(); - } - - friend bool operator<(const std::unique_ptr<QOlmSession> &lhs, const std::unique_ptr<QOlmSession> &rhs) { - return *lhs < *rhs; - } - - QOlmSession(OlmSession* session); -private: - //! Helper function for creating new sessions and handling errors. - static OlmSession* create(); - static std::variant<std::unique_ptr<QOlmSession>, OlmError> createInbound(QOlmAccount *account, const Message& preKeyMessage, bool from = false, const QString& theirIdentityKey = ""); - OlmSession* m_session; -}; - - -//using QOlmSessionPtr = std::unique_ptr<QOlmSession>; - -} //namespace Quotient - -#endif // Quotient_E2EE_ENABLED |